Page MenuHomePhabricator

D16316.diff
No OneTemporary

D16316.diff

diff --git a/resources/sql/autopatches/20160721.pack.06.version.sql b/resources/sql/autopatches/20160721.pack.06.version.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20160721.pack.06.version.sql
@@ -0,0 +1,10 @@
+CREATE TABLE {$NAMESPACE}_packages.packages_version (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ name VARCHAR(64) NOT NULL COLLATE {$COLLATE_SORT},
+ packagePHID VARBINARY(64) NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (phid),
+ UNIQUE KEY `key_package` (packagePHID, name)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20160721.pack.07.versionxaction.sql b/resources/sql/autopatches/20160721.pack.07.versionxaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20160721.pack.07.versionxaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_packages.packages_versiontransaction (
+ 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};
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
@@ -2979,6 +2979,7 @@
'PhabricatorPackagesEditor' => 'applications/packages/editor/PhabricatorPackagesEditor.php',
'PhabricatorPackagesPackage' => 'applications/packages/storage/PhabricatorPackagesPackage.php',
'PhabricatorPackagesPackageController' => 'applications/packages/controller/PhabricatorPackagesPackageController.php',
+ 'PhabricatorPackagesPackageDatasource' => 'applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php',
'PhabricatorPackagesPackageEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageEditConduitAPIMethod.php',
'PhabricatorPackagesPackageEditController' => 'applications/packages/controller/PhabricatorPackagesPackageEditController.php',
'PhabricatorPackagesPackageEditEngine' => 'applications/packages/editor/PhabricatorPackagesPackageEditEngine.php',
@@ -3016,6 +3017,23 @@
'PhabricatorPackagesQuery' => 'applications/packages/query/PhabricatorPackagesQuery.php',
'PhabricatorPackagesSchemaSpec' => 'applications/packages/storage/PhabricatorPackagesSchemaSpec.php',
'PhabricatorPackagesTransactionType' => 'applications/packages/xaction/PhabricatorPackagesTransactionType.php',
+ 'PhabricatorPackagesVersion' => 'applications/packages/storage/PhabricatorPackagesVersion.php',
+ 'PhabricatorPackagesVersionController' => 'applications/packages/controller/PhabricatorPackagesVersionController.php',
+ 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php',
+ 'PhabricatorPackagesVersionEditController' => 'applications/packages/controller/PhabricatorPackagesVersionEditController.php',
+ 'PhabricatorPackagesVersionEditEngine' => 'applications/packages/editor/PhabricatorPackagesVersionEditEngine.php',
+ 'PhabricatorPackagesVersionEditor' => 'applications/packages/editor/PhabricatorPackagesVersionEditor.php',
+ 'PhabricatorPackagesVersionListController' => 'applications/packages/controller/PhabricatorPackagesVersionListController.php',
+ 'PhabricatorPackagesVersionNameTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php',
+ 'PhabricatorPackagesVersionPHIDType' => 'applications/packages/phid/PhabricatorPackagesVersionPHIDType.php',
+ 'PhabricatorPackagesVersionPackageTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php',
+ 'PhabricatorPackagesVersionQuery' => 'applications/packages/query/PhabricatorPackagesVersionQuery.php',
+ 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php',
+ 'PhabricatorPackagesVersionSearchEngine' => 'applications/packages/query/PhabricatorPackagesVersionSearchEngine.php',
+ 'PhabricatorPackagesVersionTransaction' => 'applications/packages/storage/PhabricatorPackagesVersionTransaction.php',
+ 'PhabricatorPackagesVersionTransactionQuery' => 'applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php',
+ 'PhabricatorPackagesVersionTransactionType' => 'applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php',
+ 'PhabricatorPackagesVersionViewController' => 'applications/packages/controller/PhabricatorPackagesVersionViewController.php',
'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php',
'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php',
'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php',
@@ -7784,6 +7802,7 @@
'PhabricatorConduitResultInterface',
),
'PhabricatorPackagesPackageController' => 'PhabricatorPackagesController',
+ 'PhabricatorPackagesPackageDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorPackagesPackageEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PhabricatorPackagesPackageEditController' => 'PhabricatorPackagesPackageController',
'PhabricatorPackagesPackageEditEngine' => 'PhabricatorPackagesEditEngine',
@@ -7829,6 +7848,32 @@
'PhabricatorPackagesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPackagesSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhabricatorPackagesTransactionType' => 'PhabricatorModularTransactionType',
+ 'PhabricatorPackagesVersion' => array(
+ 'PhabricatorPackagesDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorExtendedPolicyInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorDestructibleInterface',
+ 'PhabricatorSubscribableInterface',
+ 'PhabricatorProjectInterface',
+ 'PhabricatorConduitResultInterface',
+ ),
+ 'PhabricatorPackagesVersionController' => 'PhabricatorPackagesController',
+ 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
+ 'PhabricatorPackagesVersionEditController' => 'PhabricatorPackagesVersionController',
+ 'PhabricatorPackagesVersionEditEngine' => 'PhabricatorPackagesEditEngine',
+ 'PhabricatorPackagesVersionEditor' => 'PhabricatorPackagesEditor',
+ 'PhabricatorPackagesVersionListController' => 'PhabricatorPackagesVersionController',
+ 'PhabricatorPackagesVersionNameTransaction' => 'PhabricatorPackagesVersionTransactionType',
+ 'PhabricatorPackagesVersionPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorPackagesVersionPackageTransaction' => 'PhabricatorPackagesVersionTransactionType',
+ 'PhabricatorPackagesVersionQuery' => 'PhabricatorPackagesQuery',
+ 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
+ 'PhabricatorPackagesVersionSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorPackagesVersionTransaction' => 'PhabricatorModularTransaction',
+ 'PhabricatorPackagesVersionTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'PhabricatorPackagesVersionTransactionType' => 'PhabricatorPackagesTransactionType',
+ 'PhabricatorPackagesVersionViewController' => 'PhabricatorPackagesVersionController',
'PhabricatorPagerUIExample' => 'PhabricatorUIExample',
'PhabricatorPassphraseApplication' => 'PhabricatorApplication',
'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider',
diff --git a/src/applications/packages/application/PhabricatorPackagesApplication.php b/src/applications/packages/application/PhabricatorPackagesApplication.php
--- a/src/applications/packages/application/PhabricatorPackagesApplication.php
+++ b/src/applications/packages/application/PhabricatorPackagesApplication.php
@@ -33,6 +33,8 @@
'' => 'PhabricatorPackagesPublisherViewController',
'(?P<packageKey>[^/]+)/' => array(
'' => 'PhabricatorPackagesPackageViewController',
+ '(?P<versionKey>[^/]+)/' =>
+ 'PhabricatorPackagesVersionViewController',
),
),
),
@@ -49,6 +51,12 @@
$this->getEditRoutePattern('edit/') =>
'PhabricatorPackagesPackageEditController',
),
+ 'version/' => array(
+ $this->getQueryRoutePattern() =>
+ 'PhabricatorPackagesVersionListController',
+ $this->getEditRoutePattern('edit/') =>
+ 'PhabricatorPackagesVersionEditController',
+ ),
),
);
}
diff --git a/src/applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php b/src/applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php
@@ -0,0 +1,19 @@
+<?php
+
+final class PhabricatorPackagesVersionEditConduitAPIMethod
+ extends PhabricatorEditEngineAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'packages.version.edit';
+ }
+
+ public function newEditEngine() {
+ return new PhabricatorPackagesVersionEditEngine();
+ }
+
+ public function getMethodSummary() {
+ return pht(
+ 'Apply transactions to create a new version or edit an existing one.');
+ }
+
+}
diff --git a/src/applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php b/src/applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorPackagesVersionSearchConduitAPIMethod
+ extends PhabricatorSearchEngineAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'packages.version.search';
+ }
+
+ public function newSearchEngine() {
+ return new PhabricatorPackagesVersionSearchEngine();
+ }
+
+ public function getMethodSummary() {
+ return pht('Read information about versions.');
+ }
+
+}
diff --git a/src/applications/packages/controller/PhabricatorPackagesVersionController.php b/src/applications/packages/controller/PhabricatorPackagesVersionController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/controller/PhabricatorPackagesVersionController.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorPackagesVersionController
+ extends PhabricatorPackagesController {}
diff --git a/src/applications/packages/controller/PhabricatorPackagesVersionEditController.php b/src/applications/packages/controller/PhabricatorPackagesVersionEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/controller/PhabricatorPackagesVersionEditController.php
@@ -0,0 +1,12 @@
+<?php
+
+final class PhabricatorPackagesVersionEditController
+ extends PhabricatorPackagesVersionController {
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorPackagesVersionEditEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/packages/controller/PhabricatorPackagesVersionListController.php b/src/applications/packages/controller/PhabricatorPackagesVersionListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/controller/PhabricatorPackagesVersionListController.php
@@ -0,0 +1,26 @@
+<?php
+
+final class PhabricatorPackagesVersionListController
+ extends PhabricatorPackagesVersionController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorPackagesVersionSearchEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ id(new PhabricatorPackagesVersionEditEngine())
+ ->setViewer($this->getViewer())
+ ->addActionToCrumbs($crumbs);
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/packages/controller/PhabricatorPackagesVersionViewController.php b/src/applications/packages/controller/PhabricatorPackagesVersionViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/controller/PhabricatorPackagesVersionViewController.php
@@ -0,0 +1,91 @@
+<?php
+
+final class PhabricatorPackagesVersionViewController
+ extends PhabricatorPackagesVersionController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $publisher_key = $request->getURIData('publisherKey');
+ $package_key = $request->getURIData('packageKey');
+ $full_key = $publisher_key.'/'.$package_key;
+ $version_key = $request->getURIData('versionKey');
+
+ $version = id(new PhabricatorPackagesVersionQuery())
+ ->setViewer($viewer)
+ ->withFullKeys(array($full_key))
+ ->withNames(array($version_key))
+ ->executeOne();
+ if (!$version) {
+ return new Aphront404Response();
+ }
+
+ $package = $version->getPackage();
+ $publisher = $package->getPublisher();
+
+ $crumbs = $this->buildApplicationCrumbs()
+ ->addTextCrumb($publisher->getName(), $publisher->getURI())
+ ->addTextCrumb($package->getName(), $package->getURI())
+ ->addTextCrumb($version->getName())
+ ->setBorder(true);
+
+ $header = $this->buildHeaderView($version);
+ $curtain = $this->buildCurtain($version);
+
+ $timeline = $this->buildTransactionTimeline(
+ $version,
+ new PhabricatorPackagesVersionTransactionQuery());
+
+ $version_view = id(new PHUITwoColumnView())
+ ->setHeader($header)
+ ->setCurtain($curtain)
+ ->setMainColumn($timeline);
+
+ return $this->newPage()
+ ->setCrumbs($crumbs)
+ ->setPageObjectPHIDs(
+ array(
+ $version->getPHID(),
+ ))
+ ->appendChild($version_view);
+ }
+
+
+ private function buildHeaderView(PhabricatorPackagesVersion $version) {
+ $viewer = $this->getViewer();
+ $name = $version->getName();
+
+ return id(new PHUIHeaderView())
+ ->setViewer($viewer)
+ ->setHeader($name)
+ ->setPolicyObject($version)
+ ->setHeaderIcon('fa-tag');
+ }
+
+ private function buildCurtain(PhabricatorPackagesVersion $version) {
+ $viewer = $this->getViewer();
+ $curtain = $this->newCurtainView($version);
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $version,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $id = $version->getID();
+ $edit_uri = $this->getApplicationURI("version/edit/{$id}/");
+
+ $curtain->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Version'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setHref($edit_uri));
+
+ return $curtain;
+ }
+
+}
diff --git a/src/applications/packages/editor/PhabricatorPackagesVersionEditEngine.php b/src/applications/packages/editor/PhabricatorPackagesVersionEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/editor/PhabricatorPackagesVersionEditEngine.php
@@ -0,0 +1,93 @@
+<?php
+
+final class PhabricatorPackagesVersionEditEngine
+ extends PhabricatorPackagesEditEngine {
+
+ const ENGINECONST = 'packages.version';
+
+ public function getEngineName() {
+ return pht('Package Versions');
+ }
+
+ public function getSummaryHeader() {
+ return pht('Edit Package Version Configurations');
+ }
+
+ public function getSummaryText() {
+ return pht('This engine is used to edit Packages versions.');
+ }
+
+ protected function newEditableObject() {
+ $viewer = $this->getViewer();
+ return PhabricatorPackagesVersion::initializeNewVersion($viewer);
+ }
+
+ protected function newObjectQuery() {
+ return new PhabricatorPackagesVersionQuery();
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create Version');
+ }
+
+ protected function getObjectCreateButtonText($object) {
+ return pht('Create Version');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Version: %s', $object->getName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return pht('Edit Version');
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Version');
+ }
+
+ protected function getObjectName() {
+ return pht('Version');
+ }
+
+ protected function getEditorURI() {
+ return '/packages/version/edit/';
+ }
+
+ protected function getObjectCreateCancelURI($object) {
+ return '/packages/version/';
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+ protected function buildCustomEditFields($object) {
+ $fields = array();
+
+ if ($this->getIsCreate()) {
+ $fields[] = id(new PhabricatorDatasourceEditField())
+ ->setKey('package')
+ ->setAliases(array('packagePHID'))
+ ->setLabel(pht('Package'))
+ ->setDescription(pht('Package for this version.'))
+ ->setTransactionType(
+ PhabricatorPackagesVersionPackageTransaction::TRANSACTIONTYPE)
+ ->setIsRequired(true)
+ ->setDatasource(new PhabricatorPackagesPackageDatasource())
+ ->setSingleValue($object->getPackagePHID());
+
+ $fields[] = id(new PhabricatorTextEditField())
+ ->setKey('name')
+ ->setLabel(pht('Name'))
+ ->setDescription(pht('Name of the version.'))
+ ->setTransactionType(
+ PhabricatorPackagesVersionNameTransaction::TRANSACTIONTYPE)
+ ->setIsRequired(true)
+ ->setValue($object->getName());
+ }
+
+ return $fields;
+ }
+
+}
diff --git a/src/applications/packages/editor/PhabricatorPackagesVersionEditor.php b/src/applications/packages/editor/PhabricatorPackagesVersionEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/editor/PhabricatorPackagesVersionEditor.php
@@ -0,0 +1,46 @@
+<?php
+
+final class PhabricatorPackagesVersionEditor
+ extends PhabricatorPackagesEditor {
+
+ public function getEditorObjectsDescription() {
+ return pht('Package Versions');
+ }
+
+ public function getCreateObjectTitle($author, $object) {
+ return pht('%s created this version.', $author);
+ }
+
+ public function getCreateObjectTitleForFeed($author, $object) {
+ return pht('%s created %s.', $author, $object);
+ }
+
+ 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(
+ PhabricatorPackagesVersionNameTransaction::TRANSACTIONTYPE,
+ pht('Duplicate'),
+ pht(
+ 'The version "%s" already exists for this package. Each version '.
+ 'must have a unique name.',
+ $object->getName()),
+ null);
+
+ throw new PhabricatorApplicationTransactionValidationException($errors);
+ }
+
+}
diff --git a/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php b/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
@@ -0,0 +1,45 @@
+<?php
+
+final class PhabricatorPackagesVersionPHIDType
+ extends PhabricatorPHIDType {
+
+ const TYPECONST = 'PVER';
+
+ public function getTypeName() {
+ return pht('Version');
+ }
+
+ public function newObject() {
+ return new PhabricatorPackagesVersion();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorPackagesApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorPackagesVersionQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $version = $objects[$phid];
+
+ $name = $version->getName();
+ $uri = $version->getURI();
+
+ $handle
+ ->setName($name)
+ ->setURI($uri);
+ }
+ }
+
+}
diff --git a/src/applications/packages/query/PhabricatorPackagesPackageQuery.php b/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
--- a/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesPackageQuery.php
@@ -74,31 +74,8 @@
}
if ($this->fullKeys !== null) {
- $parts = array();
- foreach ($this->fullKeys as $full_key) {
- $key_parts = explode('/', $full_key, 2);
-
- if (count($key_parts) != 2) {
- continue;
- }
-
- $parts[] = qsprintf(
- $conn,
- '(u.publisherKey = %s AND p.packageKey = %s)',
- $key_parts[0],
- $key_parts[1]);
- }
-
- // If none of the full keys we were provided were valid, we don't
- // match any results.
- if (!$parts) {
- throw new PhabricatorEmptyQueryException();
- }
-
- $where[] = qsprintf(
- $conn,
- '%Q',
- implode(' OR ', $parts));
+ $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys);
+ $where[] = qsprintf($conn, '%Q', $parts);
}
return $where;
diff --git a/src/applications/packages/query/PhabricatorPackagesQuery.php b/src/applications/packages/query/PhabricatorPackagesQuery.php
--- a/src/applications/packages/query/PhabricatorPackagesQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesQuery.php
@@ -7,4 +7,32 @@
return 'PhabricatorPackagesApplication';
}
+ protected function buildFullKeyClauseParts(
+ AphrontDatabaseConnection $conn,
+ array $full_keys) {
+
+ $parts = array();
+ foreach ($full_keys as $full_key) {
+ $key_parts = explode('/', $full_key, 2);
+
+ if (count($key_parts) != 2) {
+ continue;
+ }
+
+ $parts[] = qsprintf(
+ $conn,
+ '(u.publisherKey = %s AND p.packageKey = %s)',
+ $key_parts[0],
+ $key_parts[1]);
+ }
+
+ // If none of the full keys we were provided were valid, we don't
+ // match any results.
+ if (!$parts) {
+ throw new PhabricatorEmptyQueryException();
+ }
+
+ return implode(' OR ', $parts);
+ }
+
}
diff --git a/src/applications/packages/query/PhabricatorPackagesVersionQuery.php b/src/applications/packages/query/PhabricatorPackagesVersionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/query/PhabricatorPackagesVersionQuery.php
@@ -0,0 +1,141 @@
+<?php
+
+final class PhabricatorPackagesVersionQuery
+ extends PhabricatorPackagesQuery {
+
+ private $ids;
+ private $phids;
+ private $packagePHIDs;
+ private $fullKeys;
+ private $names;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withPackagePHIDs(array $phids) {
+ $this->packagePHIDs = $phids;
+ return $this;
+ }
+
+ public function withFullKeys(array $keys) {
+ $this->fullKeys = $keys;
+ return $this;
+ }
+
+ public function withNames(array $names) {
+ $this->names = $names;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorPackagesVersion();
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'v.id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'v.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->packagePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'v.packagePHID IN (%Ls)',
+ $this->packagePHIDs);
+ }
+
+ if ($this->names !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'v.name IN (%Ls)',
+ $this->names);
+ }
+
+ if ($this->fullKeys !== null) {
+ $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys);
+ $where[] = qsprintf($conn, '%Q', $parts);
+ }
+
+ return $where;
+ }
+
+ protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
+ $joins = parent::buildJoinClauseParts($conn);
+
+ $join_publisher = ($this->fullKeys !== null);
+ $join_package = ($this->fullKeys !== null) || $join_publisher;
+
+ if ($join_package) {
+ $package_table = new PhabricatorPackagesPackage();
+
+ $joins[] = qsprintf(
+ $conn,
+ 'JOIN %T p ON v.packagePHID = p.phid',
+ $package_table->getTableName());
+ }
+
+ if ($join_publisher) {
+ $publisher_table = new PhabricatorPackagesPublisher();
+
+ $joins[] = qsprintf(
+ $conn,
+ 'JOIN %T u ON u.phid = p.publisherPHID',
+ $publisher_table->getTableName());
+ }
+
+ return $joins;
+ }
+
+ protected function willFilterPage(array $versions) {
+ $package_phids = mpull($versions, 'getPackagePHID');
+
+ $packages = id(new PhabricatorPackagesPackageQuery())
+ ->setViewer($this->getViewer())
+ ->setParentQuery($this)
+ ->withPHIDs($package_phids)
+ ->execute();
+ $packages = mpull($packages, null, 'getPHID');
+
+ foreach ($versions as $key => $version) {
+ $package = idx($packages, $version->getPackagePHID());
+
+ if (!$package) {
+ unset($versions[$key]);
+ $this->didRejectResult($version);
+ continue;
+ }
+
+ $version->attachPackage($package);
+ }
+
+ return $versions;
+ }
+
+ protected function getPrimaryTableAlias() {
+ return 'v';
+ }
+
+
+}
diff --git a/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php b/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
@@ -0,0 +1,76 @@
+<?php
+
+final class PhabricatorPackagesVersionSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Package Versions');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorPackagesApplication';
+ }
+
+ public function newQuery() {
+ return id(new PhabricatorPackagesVersionQuery());
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ return $query;
+ }
+
+ protected function buildCustomSearchFields() {
+ return array();
+ }
+
+ protected function getURI($path) {
+ return '/packages/version/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Versions'),
+ );
+
+ 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 $versions,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+
+ assert_instances_of($versions, 'PhabricatorPackagesVersion');
+
+ $viewer = $this->requireViewer();
+
+ $list = id(new PHUIObjectItemListView())
+ ->setViewer($viewer);
+ foreach ($versions as $version) {
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($version->getName())
+ ->setHref($version->getURI());
+
+ $list->addItem($item);
+ }
+
+ return id(new PhabricatorApplicationSearchResultView())
+ ->setObjectList($list)
+ ->setNoDataString(pht('No versions found.'));
+ }
+
+}
diff --git a/src/applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php b/src/applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorPackagesVersionTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorPackagesVersionTransaction();
+ }
+
+}
diff --git a/src/applications/packages/storage/PhabricatorPackagesPackage.php b/src/applications/packages/storage/PhabricatorPackagesPackage.php
--- a/src/applications/packages/storage/PhabricatorPackagesPackage.php
+++ b/src/applications/packages/storage/PhabricatorPackagesPackage.php
@@ -154,7 +154,21 @@
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
- $this->delete();
+ $viewer = $engine->getViewer();
+
+ $this->openTransaction();
+
+ $versions = id(new PhabricatorPackagesVersionQuery())
+ ->setViewer($viewer)
+ ->withPackagePHIDs(array($this->getPHID()))
+ ->execute();
+ foreach ($versions as $version) {
+ $engine->destroyObject($version);
+ }
+
+ $this->delete();
+
+ $this->saveTransaction();
}
diff --git a/src/applications/packages/storage/PhabricatorPackagesPackage.php b/src/applications/packages/storage/PhabricatorPackagesVersion.php
copy from src/applications/packages/storage/PhabricatorPackagesPackage.php
copy to src/applications/packages/storage/PhabricatorPackagesVersion.php
--- a/src/applications/packages/storage/PhabricatorPackagesPackage.php
+++ b/src/applications/packages/storage/PhabricatorPackagesVersion.php
@@ -1,9 +1,10 @@
<?php
-final class PhabricatorPackagesPackage
+final class PhabricatorPackagesVersion
extends PhabricatorPackagesDAO
implements
PhabricatorPolicyInterface,
+ PhabricatorExtendedPolicyInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorDestructibleInterface,
PhabricatorSubscribableInterface,
@@ -11,14 +12,11 @@
PhabricatorConduitResultInterface {
protected $name;
- protected $publisherPHID;
- protected $packageKey;
- protected $viewPolicy;
- protected $editPolicy;
+ protected $packagePHID;
- private $publisher = self::ATTACHABLE;
+ private $package;
- public static function initializeNewPackage(PhabricatorUser $actor) {
+ public static function initializeNewVersion(PhabricatorUser $actor) {
return id(new self());
}
@@ -26,12 +24,11 @@
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
- 'name' => 'text64',
- 'packageKey' => 'sort64',
+ 'name' => 'sort64',
),
self::CONFIG_KEY_SCHEMA => array(
'key_package' => array(
- 'columns' => array('publisherPHID', 'packageKey'),
+ 'columns' => array('packagePHID', 'name'),
'unique' => true,
),
),
@@ -40,36 +37,32 @@
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
- PhabricatorPackagesPackagePHIDType::TYPECONST);
+ PhabricatorPackagesVersionPHIDType::TYPECONST);
}
public function getURI() {
- $full_key = $this->getFullKey();
- return "/package/{$full_key}/";
- }
+ $package = $this->getPackage();
+ $full_key = $package->getFullKey();
+ $name = $this->getName();
- public function getFullKey() {
- $publisher = $this->getPublisher();
- $publisher_key = $publisher->getPublisherKey();
- $package_key = $this->getPackageKey();
- return "{$publisher_key}/{$package_key}";
+ return "/package/{$full_key}/{$name}/";
}
- public function attachPublisher(PhabricatorPackagesPublisher $publisher) {
- $this->publisher = $publisher;
+ public function attachPackage(PhabricatorPackagesPackage $package) {
+ $this->package = $package;
return $this;
}
- public function getPublisher() {
- return $this->assertAttached($this->publisher);
+ public function getPackage() {
+ return $this->assertAttached($this->package);
}
- public static function assertValidPackageName($value) {
+ public static function assertValidVersionName($value) {
$length = phutil_utf8_strlen($value);
if (!$length) {
throw new Exception(
pht(
- 'Package name "%s" is not valid: package names are required.',
+ 'Version name "%s" is not valid: version names are required.',
$value));
}
@@ -77,37 +70,25 @@
if ($length > $max_length) {
throw new Exception(
pht(
- 'Package name "%s" is not valid: package names must not be '.
+ 'Version name "%s" is not valid: version names must not be '.
'more than %s characters long.',
$value,
new PhutilNumber($max_length)));
}
- }
- public static function assertValidPackageKey($value) {
- $length = phutil_utf8_strlen($value);
- if (!$length) {
+ if (!preg_match('/^[A-Za-z0-9.-]+\z/', $value)) {
throw new Exception(
pht(
- 'Package key "%s" is not valid: package keys are required.',
+ 'Version name "%s" is not valid: version names may only contain '.
+ 'latin letters, digits, periods, and hyphens.',
$value));
}
- $max_length = 64;
- if ($length > $max_length) {
- throw new Exception(
- pht(
- 'Package key "%s" is not valid: package keys must not be '.
- 'more than %s characters long.',
- $value,
- new PhutilNumber($max_length)));
- }
-
- if (!preg_match('/^[a-z]+\z/', $value)) {
+ if (preg_match('/^[.-]|[.-]$/', $value)) {
throw new Exception(
pht(
- 'Package key "%s" is not valid: package keys may only contain '.
- 'lowercase latin letters.',
+ 'Version name "%s" is not valid: version names may not start or '.
+ 'end with a period or hyphen.',
$value));
}
}
@@ -134,9 +115,9 @@
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
- return $this->getViewPolicy();
+ return PhabricatorPolicies::getMostOpenPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
- return $this->getEditPolicy();
+ return PhabricatorPolicies::POLICY_USER;
}
}
@@ -149,6 +130,19 @@
}
+/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
+
+
+ public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
+ return array(
+ array(
+ $this->getPackage(),
+ $capability,
+ ),
+ );
+ }
+
+
/* -( PhabricatorDestructibleInterface )----------------------------------- */
@@ -162,7 +156,7 @@
public function getApplicationTransactionEditor() {
- return new PhabricatorPackagesPackageEditor();
+ return new PhabricatorPackagesVersionEditor();
}
public function getApplicationTransactionObject() {
@@ -170,7 +164,7 @@
}
public function getApplicationTransactionTemplate() {
- return new PhabricatorPackagesPackageTransaction();
+ return new PhabricatorPackagesVersionTransaction();
}
public function willRenderTimeline(
@@ -188,29 +182,13 @@
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
- ->setDescription(pht('The name of the package.')),
- id(new PhabricatorConduitSearchFieldSpecification())
- ->setKey('packageKey')
- ->setType('string')
- ->setDescription(pht('The unique key of the package.')),
+ ->setDescription(pht('The name of the version.')),
);
}
public function getFieldValuesForConduit() {
- $publisher = $this->getPublisher();
-
- $publisher_map = array(
- 'id' => (int)$publisher->getID(),
- 'phid' => $publisher->getPHID(),
- 'name' => $publisher->getName(),
- 'publisherKey' => $publisher->getPublisherKey(),
- );
-
return array(
'name' => $this->getName(),
- 'packageKey' => $this->getPackageKey(),
- 'fullKey' => $this->getFullKey(),
- 'publisher' => $publisher_map,
);
}
diff --git a/src/applications/packages/storage/PhabricatorPackagesVersionTransaction.php b/src/applications/packages/storage/PhabricatorPackagesVersionTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/storage/PhabricatorPackagesVersionTransaction.php
@@ -0,0 +1,18 @@
+<?php
+
+final class PhabricatorPackagesVersionTransaction
+ extends PhabricatorModularTransaction {
+
+ public function getApplicationName() {
+ return 'packages';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorPackagesVersionPHIDType::TYPECONST;
+ }
+
+ public function getBaseTransactionClass() {
+ return 'PhabricatorPackagesVersionTransactionType';
+ }
+
+}
diff --git a/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php b/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
@@ -0,0 +1,35 @@
+<?php
+
+final class PhabricatorPackagesPackageDatasource
+ extends PhabricatorTypeaheadDatasource {
+
+ public function getBrowseTitle() {
+ return pht('Browse Packagess');
+ }
+
+ public function getPlaceholderText() {
+ return pht('Type a package name...');
+ }
+
+ public function getDatasourceApplicationClass() {
+ return 'PhabricatorPackagesApplication';
+ }
+
+ public function loadResults() {
+ $viewer = $this->getViewer();
+ $raw_query = $this->getRawQuery();
+
+ $package_query = id(new PhabricatorPackagesPackageQuery());
+ $packages = $this->executeQuery($package_query);
+
+ $results = array();
+ foreach ($packages as $package) {
+ $results[] = id(new PhabricatorTypeaheadResult())
+ ->setName($package->getName())
+ ->setPHID($package->getPHID());
+ }
+
+ return $this->filterResultsAgainstTokens($results);
+ }
+
+}
diff --git a/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php b/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
--- a/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
+++ b/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
@@ -16,7 +16,8 @@
public function validateTransactions($object, array $xactions) {
$errors = array();
- if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
+ $current_value = $object->getPublisherPHID();
+ if ($this->isEmptyTextTransaction($current_value, $xactions)) {
$errors[] = $this->newRequiredError(
pht(
'You must select a publisher when creating a package.'));
diff --git a/src/applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php b/src/applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php
@@ -0,0 +1,62 @@
+<?php
+
+final class PhabricatorPackagesVersionNameTransaction
+ extends PhabricatorPackagesVersionTransactionType {
+
+ const TRANSACTIONTYPE = 'packages.version.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 version 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('Versions must have a name.'));
+ return $errors;
+ }
+
+ foreach ($xactions as $xaction) {
+ $value = $xaction->getNewValue();
+ try {
+ PhabricatorPackagesVersion::assertValidVersionName($value);
+ } catch (Exception $ex) {
+ $errors[] = $this->newInvalidError($ex->getMessage(), $xaction);
+ }
+ }
+
+ if (!$this->isNewObject()) {
+ foreach ($xactions as $xaction) {
+ $errors[] = $this->newInvalidError(
+ pht('Once a version is created, its name can not be changed.'),
+ $xaction);
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php b/src/applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php
copy from src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
copy to src/applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php
--- a/src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
+++ b/src/applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php
@@ -1,43 +1,43 @@
<?php
-final class PhabricatorPackagesPackagePublisherTransaction
- extends PhabricatorPackagesPackageTransactionType {
+final class PhabricatorPackagesVersionPackageTransaction
+ extends PhabricatorPackagesVersionTransactionType {
- const TRANSACTIONTYPE = 'packages.package.publisher';
+ const TRANSACTIONTYPE = 'packages.version.package';
public function generateOldValue($object) {
- return $object->getPublisherPHID();
+ return $object->getPackagePHID();
}
public function applyInternalEffects($object, $value) {
- $object->setPublisherPHID($value);
+ $object->setPackagePHID($value);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
- if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
+ if ($this->isEmptyTextTransaction($object->getPackagePHID(), $xactions)) {
$errors[] = $this->newRequiredError(
pht(
- 'You must select a publisher when creating a package.'));
+ 'You must select a package when creating a version'));
return $errors;
}
if (!$this->isNewObject()) {
foreach ($xactions as $xaction) {
$errors[] = $this->newInvalidError(
- pht('Once a package is created, its publisher can not be changed.'),
+ pht('Once a version is created, its package can not be changed.'),
$xaction);
}
}
$viewer = $this->getActor();
foreach ($xactions as $xaction) {
- $publisher_phid = $xaction->getNewValue();
+ $package_phid = $xaction->getNewValue();
- $publisher = id(new PhabricatorPackagesPublisherQuery())
+ $package = id(new PhabricatorPackagesPackageQuery())
->setViewer($viewer)
- ->withPHIDs(array($publisher_phid))
+ ->withPHIDs(array($package_phid))
->setRaisePolicyExceptions(false)
->requireCapabilities(
array(
@@ -46,18 +46,18 @@
))
->executeOne();
- if (!$publisher) {
+ if (!$package) {
$errors[] = $this->newInvalidError(
pht(
- 'Publisher "%s" is invalid: the publisher must exist and you '.
+ 'Package "%s" is invalid: the package must exist and you '.
'must have permission to edit it in order to create a new '.
'package.',
- $publisher_phid),
+ $package_phid),
$xaction);
continue;
}
- $object->attachPublisher($publisher);
+ $object->attachPackage($package);
}
return $errors;
diff --git a/src/applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php b/src/applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorPackagesVersionTransactionType
+ extends PhabricatorPackagesTransactionType {}

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 19, 8:21 AM (21 h, 25 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6906801
Default Alt Text
D16316.diff (44 KB)

Event Timeline