@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add PackagesVersion

Summary:
Ref T8116. A version has:

- a package (like "Arcanist") which it belongs to;
- a name (like "v3.1.5").

The name is immutable and unique, like the package key and publisher key.

Policy stuff:

- Versions have the exact same policies as their packages.
- You must be able to edit a package to create new versions of it.

This is still entirely uninteresting.

Test Plan: {F1731703}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T8116

Differential Revision: https://secure.phabricator.com/D16316

+1095 -27
+10
resources/sql/autopatches/20160721.pack.06.version.sql
··· 1 + CREATE TABLE {$NAMESPACE}_packages.packages_version ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + phid VARBINARY(64) NOT NULL, 4 + name VARCHAR(64) NOT NULL COLLATE {$COLLATE_SORT}, 5 + packagePHID VARBINARY(64) NOT NULL, 6 + dateCreated INT UNSIGNED NOT NULL, 7 + dateModified INT UNSIGNED NOT NULL, 8 + UNIQUE KEY `key_phid` (phid), 9 + UNIQUE KEY `key_package` (packagePHID, name) 10 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+19
resources/sql/autopatches/20160721.pack.07.versionxaction.sql
··· 1 + CREATE TABLE {$NAMESPACE}_packages.packages_versiontransaction ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + phid VARBINARY(64) NOT NULL, 4 + authorPHID VARBINARY(64) NOT NULL, 5 + objectPHID VARBINARY(64) NOT NULL, 6 + viewPolicy VARBINARY(64) NOT NULL, 7 + editPolicy VARBINARY(64) NOT NULL, 8 + commentPHID VARBINARY(64) DEFAULT NULL, 9 + commentVersion INT UNSIGNED NOT NULL, 10 + transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL, 11 + oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL, 12 + newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL, 13 + contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL, 14 + metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL, 15 + dateCreated INT UNSIGNED NOT NULL, 16 + dateModified INT UNSIGNED NOT NULL, 17 + UNIQUE KEY `key_phid` (`phid`), 18 + KEY `key_object` (`objectPHID`) 19 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+45
src/__phutil_library_map__.php
··· 2979 2979 'PhabricatorPackagesEditor' => 'applications/packages/editor/PhabricatorPackagesEditor.php', 2980 2980 'PhabricatorPackagesPackage' => 'applications/packages/storage/PhabricatorPackagesPackage.php', 2981 2981 'PhabricatorPackagesPackageController' => 'applications/packages/controller/PhabricatorPackagesPackageController.php', 2982 + 'PhabricatorPackagesPackageDatasource' => 'applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php', 2982 2983 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageEditConduitAPIMethod.php', 2983 2984 'PhabricatorPackagesPackageEditController' => 'applications/packages/controller/PhabricatorPackagesPackageEditController.php', 2984 2985 'PhabricatorPackagesPackageEditEngine' => 'applications/packages/editor/PhabricatorPackagesPackageEditEngine.php', ··· 3016 3017 'PhabricatorPackagesQuery' => 'applications/packages/query/PhabricatorPackagesQuery.php', 3017 3018 'PhabricatorPackagesSchemaSpec' => 'applications/packages/storage/PhabricatorPackagesSchemaSpec.php', 3018 3019 'PhabricatorPackagesTransactionType' => 'applications/packages/xaction/PhabricatorPackagesTransactionType.php', 3020 + 'PhabricatorPackagesVersion' => 'applications/packages/storage/PhabricatorPackagesVersion.php', 3021 + 'PhabricatorPackagesVersionController' => 'applications/packages/controller/PhabricatorPackagesVersionController.php', 3022 + 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php', 3023 + 'PhabricatorPackagesVersionEditController' => 'applications/packages/controller/PhabricatorPackagesVersionEditController.php', 3024 + 'PhabricatorPackagesVersionEditEngine' => 'applications/packages/editor/PhabricatorPackagesVersionEditEngine.php', 3025 + 'PhabricatorPackagesVersionEditor' => 'applications/packages/editor/PhabricatorPackagesVersionEditor.php', 3026 + 'PhabricatorPackagesVersionListController' => 'applications/packages/controller/PhabricatorPackagesVersionListController.php', 3027 + 'PhabricatorPackagesVersionNameTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php', 3028 + 'PhabricatorPackagesVersionPHIDType' => 'applications/packages/phid/PhabricatorPackagesVersionPHIDType.php', 3029 + 'PhabricatorPackagesVersionPackageTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php', 3030 + 'PhabricatorPackagesVersionQuery' => 'applications/packages/query/PhabricatorPackagesVersionQuery.php', 3031 + 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php', 3032 + 'PhabricatorPackagesVersionSearchEngine' => 'applications/packages/query/PhabricatorPackagesVersionSearchEngine.php', 3033 + 'PhabricatorPackagesVersionTransaction' => 'applications/packages/storage/PhabricatorPackagesVersionTransaction.php', 3034 + 'PhabricatorPackagesVersionTransactionQuery' => 'applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php', 3035 + 'PhabricatorPackagesVersionTransactionType' => 'applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php', 3036 + 'PhabricatorPackagesVersionViewController' => 'applications/packages/controller/PhabricatorPackagesVersionViewController.php', 3019 3037 'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php', 3020 3038 'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php', 3021 3039 'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php', ··· 7784 7802 'PhabricatorConduitResultInterface', 7785 7803 ), 7786 7804 'PhabricatorPackagesPackageController' => 'PhabricatorPackagesController', 7805 + 'PhabricatorPackagesPackageDatasource' => 'PhabricatorTypeaheadDatasource', 7787 7806 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 7788 7807 'PhabricatorPackagesPackageEditController' => 'PhabricatorPackagesPackageController', 7789 7808 'PhabricatorPackagesPackageEditEngine' => 'PhabricatorPackagesEditEngine', ··· 7829 7848 'PhabricatorPackagesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7830 7849 'PhabricatorPackagesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 7831 7850 'PhabricatorPackagesTransactionType' => 'PhabricatorModularTransactionType', 7851 + 'PhabricatorPackagesVersion' => array( 7852 + 'PhabricatorPackagesDAO', 7853 + 'PhabricatorPolicyInterface', 7854 + 'PhabricatorExtendedPolicyInterface', 7855 + 'PhabricatorApplicationTransactionInterface', 7856 + 'PhabricatorDestructibleInterface', 7857 + 'PhabricatorSubscribableInterface', 7858 + 'PhabricatorProjectInterface', 7859 + 'PhabricatorConduitResultInterface', 7860 + ), 7861 + 'PhabricatorPackagesVersionController' => 'PhabricatorPackagesController', 7862 + 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 7863 + 'PhabricatorPackagesVersionEditController' => 'PhabricatorPackagesVersionController', 7864 + 'PhabricatorPackagesVersionEditEngine' => 'PhabricatorPackagesEditEngine', 7865 + 'PhabricatorPackagesVersionEditor' => 'PhabricatorPackagesEditor', 7866 + 'PhabricatorPackagesVersionListController' => 'PhabricatorPackagesVersionController', 7867 + 'PhabricatorPackagesVersionNameTransaction' => 'PhabricatorPackagesVersionTransactionType', 7868 + 'PhabricatorPackagesVersionPHIDType' => 'PhabricatorPHIDType', 7869 + 'PhabricatorPackagesVersionPackageTransaction' => 'PhabricatorPackagesVersionTransactionType', 7870 + 'PhabricatorPackagesVersionQuery' => 'PhabricatorPackagesQuery', 7871 + 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 7872 + 'PhabricatorPackagesVersionSearchEngine' => 'PhabricatorApplicationSearchEngine', 7873 + 'PhabricatorPackagesVersionTransaction' => 'PhabricatorModularTransaction', 7874 + 'PhabricatorPackagesVersionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7875 + 'PhabricatorPackagesVersionTransactionType' => 'PhabricatorPackagesTransactionType', 7876 + 'PhabricatorPackagesVersionViewController' => 'PhabricatorPackagesVersionController', 7832 7877 'PhabricatorPagerUIExample' => 'PhabricatorUIExample', 7833 7878 'PhabricatorPassphraseApplication' => 'PhabricatorApplication', 7834 7879 'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider',
+8
src/applications/packages/application/PhabricatorPackagesApplication.php
··· 33 33 '' => 'PhabricatorPackagesPublisherViewController', 34 34 '(?P<packageKey>[^/]+)/' => array( 35 35 '' => 'PhabricatorPackagesPackageViewController', 36 + '(?P<versionKey>[^/]+)/' => 37 + 'PhabricatorPackagesVersionViewController', 36 38 ), 37 39 ), 38 40 ), ··· 48 50 'PhabricatorPackagesPackageListController', 49 51 $this->getEditRoutePattern('edit/') => 50 52 'PhabricatorPackagesPackageEditController', 53 + ), 54 + 'version/' => array( 55 + $this->getQueryRoutePattern() => 56 + 'PhabricatorPackagesVersionListController', 57 + $this->getEditRoutePattern('edit/') => 58 + 'PhabricatorPackagesVersionEditController', 51 59 ), 52 60 ), 53 61 );
+19
src/applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionEditConduitAPIMethod 4 + extends PhabricatorEditEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'packages.version.edit'; 8 + } 9 + 10 + public function newEditEngine() { 11 + return new PhabricatorPackagesVersionEditEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht( 16 + 'Apply transactions to create a new version or edit an existing one.'); 17 + } 18 + 19 + }
+18
src/applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionSearchConduitAPIMethod 4 + extends PhabricatorSearchEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'packages.version.search'; 8 + } 9 + 10 + public function newSearchEngine() { 11 + return new PhabricatorPackagesVersionSearchEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht('Read information about versions.'); 16 + } 17 + 18 + }
+4
src/applications/packages/controller/PhabricatorPackagesVersionController.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorPackagesVersionController 4 + extends PhabricatorPackagesController {}
+12
src/applications/packages/controller/PhabricatorPackagesVersionEditController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionEditController 4 + extends PhabricatorPackagesVersionController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + return id(new PhabricatorPackagesVersionEditEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 10 + } 11 + 12 + }
+26
src/applications/packages/controller/PhabricatorPackagesVersionListController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionListController 4 + extends PhabricatorPackagesVersionController { 5 + 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + return id(new PhabricatorPackagesVersionSearchEngine()) 12 + ->setController($this) 13 + ->buildResponse(); 14 + } 15 + 16 + protected function buildApplicationCrumbs() { 17 + $crumbs = parent::buildApplicationCrumbs(); 18 + 19 + id(new PhabricatorPackagesVersionEditEngine()) 20 + ->setViewer($this->getViewer()) 21 + ->addActionToCrumbs($crumbs); 22 + 23 + return $crumbs; 24 + } 25 + 26 + }
+91
src/applications/packages/controller/PhabricatorPackagesVersionViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionViewController 4 + extends PhabricatorPackagesVersionController { 5 + 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + $viewer = $request->getViewer(); 12 + 13 + $publisher_key = $request->getURIData('publisherKey'); 14 + $package_key = $request->getURIData('packageKey'); 15 + $full_key = $publisher_key.'/'.$package_key; 16 + $version_key = $request->getURIData('versionKey'); 17 + 18 + $version = id(new PhabricatorPackagesVersionQuery()) 19 + ->setViewer($viewer) 20 + ->withFullKeys(array($full_key)) 21 + ->withNames(array($version_key)) 22 + ->executeOne(); 23 + if (!$version) { 24 + return new Aphront404Response(); 25 + } 26 + 27 + $package = $version->getPackage(); 28 + $publisher = $package->getPublisher(); 29 + 30 + $crumbs = $this->buildApplicationCrumbs() 31 + ->addTextCrumb($publisher->getName(), $publisher->getURI()) 32 + ->addTextCrumb($package->getName(), $package->getURI()) 33 + ->addTextCrumb($version->getName()) 34 + ->setBorder(true); 35 + 36 + $header = $this->buildHeaderView($version); 37 + $curtain = $this->buildCurtain($version); 38 + 39 + $timeline = $this->buildTransactionTimeline( 40 + $version, 41 + new PhabricatorPackagesVersionTransactionQuery()); 42 + 43 + $version_view = id(new PHUITwoColumnView()) 44 + ->setHeader($header) 45 + ->setCurtain($curtain) 46 + ->setMainColumn($timeline); 47 + 48 + return $this->newPage() 49 + ->setCrumbs($crumbs) 50 + ->setPageObjectPHIDs( 51 + array( 52 + $version->getPHID(), 53 + )) 54 + ->appendChild($version_view); 55 + } 56 + 57 + 58 + private function buildHeaderView(PhabricatorPackagesVersion $version) { 59 + $viewer = $this->getViewer(); 60 + $name = $version->getName(); 61 + 62 + return id(new PHUIHeaderView()) 63 + ->setViewer($viewer) 64 + ->setHeader($name) 65 + ->setPolicyObject($version) 66 + ->setHeaderIcon('fa-tag'); 67 + } 68 + 69 + private function buildCurtain(PhabricatorPackagesVersion $version) { 70 + $viewer = $this->getViewer(); 71 + $curtain = $this->newCurtainView($version); 72 + 73 + $can_edit = PhabricatorPolicyFilter::hasCapability( 74 + $viewer, 75 + $version, 76 + PhabricatorPolicyCapability::CAN_EDIT); 77 + 78 + $id = $version->getID(); 79 + $edit_uri = $this->getApplicationURI("version/edit/{$id}/"); 80 + 81 + $curtain->addAction( 82 + id(new PhabricatorActionView()) 83 + ->setName(pht('Edit Version')) 84 + ->setIcon('fa-pencil') 85 + ->setDisabled(!$can_edit) 86 + ->setHref($edit_uri)); 87 + 88 + return $curtain; 89 + } 90 + 91 + }
+93
src/applications/packages/editor/PhabricatorPackagesVersionEditEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionEditEngine 4 + extends PhabricatorPackagesEditEngine { 5 + 6 + const ENGINECONST = 'packages.version'; 7 + 8 + public function getEngineName() { 9 + return pht('Package Versions'); 10 + } 11 + 12 + public function getSummaryHeader() { 13 + return pht('Edit Package Version Configurations'); 14 + } 15 + 16 + public function getSummaryText() { 17 + return pht('This engine is used to edit Packages versions.'); 18 + } 19 + 20 + protected function newEditableObject() { 21 + $viewer = $this->getViewer(); 22 + return PhabricatorPackagesVersion::initializeNewVersion($viewer); 23 + } 24 + 25 + protected function newObjectQuery() { 26 + return new PhabricatorPackagesVersionQuery(); 27 + } 28 + 29 + protected function getObjectCreateTitleText($object) { 30 + return pht('Create Version'); 31 + } 32 + 33 + protected function getObjectCreateButtonText($object) { 34 + return pht('Create Version'); 35 + } 36 + 37 + protected function getObjectEditTitleText($object) { 38 + return pht('Edit Version: %s', $object->getName()); 39 + } 40 + 41 + protected function getObjectEditShortText($object) { 42 + return pht('Edit Version'); 43 + } 44 + 45 + protected function getObjectCreateShortText() { 46 + return pht('Create Version'); 47 + } 48 + 49 + protected function getObjectName() { 50 + return pht('Version'); 51 + } 52 + 53 + protected function getEditorURI() { 54 + return '/packages/version/edit/'; 55 + } 56 + 57 + protected function getObjectCreateCancelURI($object) { 58 + return '/packages/version/'; 59 + } 60 + 61 + protected function getObjectViewURI($object) { 62 + return $object->getURI(); 63 + } 64 + 65 + protected function buildCustomEditFields($object) { 66 + $fields = array(); 67 + 68 + if ($this->getIsCreate()) { 69 + $fields[] = id(new PhabricatorDatasourceEditField()) 70 + ->setKey('package') 71 + ->setAliases(array('packagePHID')) 72 + ->setLabel(pht('Package')) 73 + ->setDescription(pht('Package for this version.')) 74 + ->setTransactionType( 75 + PhabricatorPackagesVersionPackageTransaction::TRANSACTIONTYPE) 76 + ->setIsRequired(true) 77 + ->setDatasource(new PhabricatorPackagesPackageDatasource()) 78 + ->setSingleValue($object->getPackagePHID()); 79 + 80 + $fields[] = id(new PhabricatorTextEditField()) 81 + ->setKey('name') 82 + ->setLabel(pht('Name')) 83 + ->setDescription(pht('Name of the version.')) 84 + ->setTransactionType( 85 + PhabricatorPackagesVersionNameTransaction::TRANSACTIONTYPE) 86 + ->setIsRequired(true) 87 + ->setValue($object->getName()); 88 + } 89 + 90 + return $fields; 91 + } 92 + 93 + }
+46
src/applications/packages/editor/PhabricatorPackagesVersionEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionEditor 4 + extends PhabricatorPackagesEditor { 5 + 6 + public function getEditorObjectsDescription() { 7 + return pht('Package Versions'); 8 + } 9 + 10 + public function getCreateObjectTitle($author, $object) { 11 + return pht('%s created this version.', $author); 12 + } 13 + 14 + public function getCreateObjectTitleForFeed($author, $object) { 15 + return pht('%s created %s.', $author, $object); 16 + } 17 + 18 + protected function shouldPublishFeedStory( 19 + PhabricatorLiskDAO $object, 20 + array $xactions) { 21 + return true; 22 + } 23 + 24 + protected function getMailTo(PhabricatorLiskDAO $object) { 25 + return array(); 26 + } 27 + 28 + protected function didCatchDuplicateKeyException( 29 + PhabricatorLiskDAO $object, 30 + array $xactions, 31 + Exception $ex) { 32 + 33 + $errors = array(); 34 + $errors[] = new PhabricatorApplicationTransactionValidationError( 35 + PhabricatorPackagesVersionNameTransaction::TRANSACTIONTYPE, 36 + pht('Duplicate'), 37 + pht( 38 + 'The version "%s" already exists for this package. Each version '. 39 + 'must have a unique name.', 40 + $object->getName()), 41 + null); 42 + 43 + throw new PhabricatorApplicationTransactionValidationException($errors); 44 + } 45 + 46 + }
+45
src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionPHIDType 4 + extends PhabricatorPHIDType { 5 + 6 + const TYPECONST = 'PVER'; 7 + 8 + public function getTypeName() { 9 + return pht('Version'); 10 + } 11 + 12 + public function newObject() { 13 + return new PhabricatorPackagesVersion(); 14 + } 15 + 16 + public function getPHIDTypeApplicationClass() { 17 + return 'PhabricatorPackagesApplication'; 18 + } 19 + 20 + protected function buildQueryForObjects( 21 + PhabricatorObjectQuery $query, 22 + array $phids) { 23 + 24 + return id(new PhabricatorPackagesVersionQuery()) 25 + ->withPHIDs($phids); 26 + } 27 + 28 + public function loadHandles( 29 + PhabricatorHandleQuery $query, 30 + array $handles, 31 + array $objects) { 32 + 33 + foreach ($handles as $phid => $handle) { 34 + $version = $objects[$phid]; 35 + 36 + $name = $version->getName(); 37 + $uri = $version->getURI(); 38 + 39 + $handle 40 + ->setName($name) 41 + ->setURI($uri); 42 + } 43 + } 44 + 45 + }
+2 -25
src/applications/packages/query/PhabricatorPackagesPackageQuery.php
··· 74 74 } 75 75 76 76 if ($this->fullKeys !== null) { 77 - $parts = array(); 78 - foreach ($this->fullKeys as $full_key) { 79 - $key_parts = explode('/', $full_key, 2); 80 - 81 - if (count($key_parts) != 2) { 82 - continue; 83 - } 84 - 85 - $parts[] = qsprintf( 86 - $conn, 87 - '(u.publisherKey = %s AND p.packageKey = %s)', 88 - $key_parts[0], 89 - $key_parts[1]); 90 - } 91 - 92 - // If none of the full keys we were provided were valid, we don't 93 - // match any results. 94 - if (!$parts) { 95 - throw new PhabricatorEmptyQueryException(); 96 - } 97 - 98 - $where[] = qsprintf( 99 - $conn, 100 - '%Q', 101 - implode(' OR ', $parts)); 77 + $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys); 78 + $where[] = qsprintf($conn, '%Q', $parts); 102 79 } 103 80 104 81 return $where;
+28
src/applications/packages/query/PhabricatorPackagesQuery.php
··· 7 7 return 'PhabricatorPackagesApplication'; 8 8 } 9 9 10 + protected function buildFullKeyClauseParts( 11 + AphrontDatabaseConnection $conn, 12 + array $full_keys) { 13 + 14 + $parts = array(); 15 + foreach ($full_keys as $full_key) { 16 + $key_parts = explode('/', $full_key, 2); 17 + 18 + if (count($key_parts) != 2) { 19 + continue; 20 + } 21 + 22 + $parts[] = qsprintf( 23 + $conn, 24 + '(u.publisherKey = %s AND p.packageKey = %s)', 25 + $key_parts[0], 26 + $key_parts[1]); 27 + } 28 + 29 + // If none of the full keys we were provided were valid, we don't 30 + // match any results. 31 + if (!$parts) { 32 + throw new PhabricatorEmptyQueryException(); 33 + } 34 + 35 + return implode(' OR ', $parts); 36 + } 37 + 10 38 }
+141
src/applications/packages/query/PhabricatorPackagesVersionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionQuery 4 + extends PhabricatorPackagesQuery { 5 + 6 + private $ids; 7 + private $phids; 8 + private $packagePHIDs; 9 + private $fullKeys; 10 + private $names; 11 + 12 + public function withIDs(array $ids) { 13 + $this->ids = $ids; 14 + return $this; 15 + } 16 + 17 + public function withPHIDs(array $phids) { 18 + $this->phids = $phids; 19 + return $this; 20 + } 21 + 22 + public function withPackagePHIDs(array $phids) { 23 + $this->packagePHIDs = $phids; 24 + return $this; 25 + } 26 + 27 + public function withFullKeys(array $keys) { 28 + $this->fullKeys = $keys; 29 + return $this; 30 + } 31 + 32 + public function withNames(array $names) { 33 + $this->names = $names; 34 + return $this; 35 + } 36 + 37 + public function newResultObject() { 38 + return new PhabricatorPackagesVersion(); 39 + } 40 + 41 + protected function loadPage() { 42 + return $this->loadStandardPage($this->newResultObject()); 43 + } 44 + 45 + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 46 + $where = parent::buildWhereClauseParts($conn); 47 + 48 + if ($this->ids !== null) { 49 + $where[] = qsprintf( 50 + $conn, 51 + 'v.id IN (%Ld)', 52 + $this->ids); 53 + } 54 + 55 + if ($this->phids !== null) { 56 + $where[] = qsprintf( 57 + $conn, 58 + 'v.phid IN (%Ls)', 59 + $this->phids); 60 + } 61 + 62 + if ($this->packagePHIDs !== null) { 63 + $where[] = qsprintf( 64 + $conn, 65 + 'v.packagePHID IN (%Ls)', 66 + $this->packagePHIDs); 67 + } 68 + 69 + if ($this->names !== null) { 70 + $where[] = qsprintf( 71 + $conn, 72 + 'v.name IN (%Ls)', 73 + $this->names); 74 + } 75 + 76 + if ($this->fullKeys !== null) { 77 + $parts = $this->buildFullKeyClauseParts($conn, $this->fullKeys); 78 + $where[] = qsprintf($conn, '%Q', $parts); 79 + } 80 + 81 + return $where; 82 + } 83 + 84 + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { 85 + $joins = parent::buildJoinClauseParts($conn); 86 + 87 + $join_publisher = ($this->fullKeys !== null); 88 + $join_package = ($this->fullKeys !== null) || $join_publisher; 89 + 90 + if ($join_package) { 91 + $package_table = new PhabricatorPackagesPackage(); 92 + 93 + $joins[] = qsprintf( 94 + $conn, 95 + 'JOIN %T p ON v.packagePHID = p.phid', 96 + $package_table->getTableName()); 97 + } 98 + 99 + if ($join_publisher) { 100 + $publisher_table = new PhabricatorPackagesPublisher(); 101 + 102 + $joins[] = qsprintf( 103 + $conn, 104 + 'JOIN %T u ON u.phid = p.publisherPHID', 105 + $publisher_table->getTableName()); 106 + } 107 + 108 + return $joins; 109 + } 110 + 111 + protected function willFilterPage(array $versions) { 112 + $package_phids = mpull($versions, 'getPackagePHID'); 113 + 114 + $packages = id(new PhabricatorPackagesPackageQuery()) 115 + ->setViewer($this->getViewer()) 116 + ->setParentQuery($this) 117 + ->withPHIDs($package_phids) 118 + ->execute(); 119 + $packages = mpull($packages, null, 'getPHID'); 120 + 121 + foreach ($versions as $key => $version) { 122 + $package = idx($packages, $version->getPackagePHID()); 123 + 124 + if (!$package) { 125 + unset($versions[$key]); 126 + $this->didRejectResult($version); 127 + continue; 128 + } 129 + 130 + $version->attachPackage($package); 131 + } 132 + 133 + return $versions; 134 + } 135 + 136 + protected function getPrimaryTableAlias() { 137 + return 'v'; 138 + } 139 + 140 + 141 + }
+76
src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Package Versions'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorPackagesApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return id(new PhabricatorPackagesVersionQuery()); 16 + } 17 + 18 + protected function buildQueryFromParameters(array $map) { 19 + $query = $this->newQuery(); 20 + 21 + return $query; 22 + } 23 + 24 + protected function buildCustomSearchFields() { 25 + return array(); 26 + } 27 + 28 + protected function getURI($path) { 29 + return '/packages/version/'.$path; 30 + } 31 + 32 + protected function getBuiltinQueryNames() { 33 + $names = array( 34 + 'all' => pht('All Versions'), 35 + ); 36 + 37 + return $names; 38 + } 39 + 40 + public function buildSavedQueryFromBuiltin($query_key) { 41 + $query = $this->newSavedQuery(); 42 + $query->setQueryKey($query_key); 43 + 44 + switch ($query_key) { 45 + case 'all': 46 + return $query; 47 + } 48 + 49 + return parent::buildSavedQueryFromBuiltin($query_key); 50 + } 51 + 52 + protected function renderResultList( 53 + array $versions, 54 + PhabricatorSavedQuery $query, 55 + array $handles) { 56 + 57 + assert_instances_of($versions, 'PhabricatorPackagesVersion'); 58 + 59 + $viewer = $this->requireViewer(); 60 + 61 + $list = id(new PHUIObjectItemListView()) 62 + ->setViewer($viewer); 63 + foreach ($versions as $version) { 64 + $item = id(new PHUIObjectItemView()) 65 + ->setHeader($version->getName()) 66 + ->setHref($version->getURI()); 67 + 68 + $list->addItem($item); 69 + } 70 + 71 + return id(new PhabricatorApplicationSearchResultView()) 72 + ->setObjectList($list) 73 + ->setNoDataString(pht('No versions found.')); 74 + } 75 + 76 + }
+10
src/applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + public function getTemplateApplicationTransaction() { 7 + return new PhabricatorPackagesVersionTransaction(); 8 + } 9 + 10 + }
+15 -1
src/applications/packages/storage/PhabricatorPackagesPackage.php
··· 154 154 155 155 public function destroyObjectPermanently( 156 156 PhabricatorDestructionEngine $engine) { 157 - $this->delete(); 157 + $viewer = $engine->getViewer(); 158 + 159 + $this->openTransaction(); 160 + 161 + $versions = id(new PhabricatorPackagesVersionQuery()) 162 + ->setViewer($viewer) 163 + ->withPackagePHIDs(array($this->getPHID())) 164 + ->execute(); 165 + foreach ($versions as $version) { 166 + $engine->destroyObject($version); 167 + } 168 + 169 + $this->delete(); 170 + 171 + $this->saveTransaction(); 158 172 } 159 173 160 174
+200
src/applications/packages/storage/PhabricatorPackagesVersion.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersion 4 + extends PhabricatorPackagesDAO 5 + implements 6 + PhabricatorPolicyInterface, 7 + PhabricatorExtendedPolicyInterface, 8 + PhabricatorApplicationTransactionInterface, 9 + PhabricatorDestructibleInterface, 10 + PhabricatorSubscribableInterface, 11 + PhabricatorProjectInterface, 12 + PhabricatorConduitResultInterface { 13 + 14 + protected $name; 15 + protected $packagePHID; 16 + 17 + private $package; 18 + 19 + public static function initializeNewVersion(PhabricatorUser $actor) { 20 + return id(new self()); 21 + } 22 + 23 + protected function getConfiguration() { 24 + return array( 25 + self::CONFIG_AUX_PHID => true, 26 + self::CONFIG_COLUMN_SCHEMA => array( 27 + 'name' => 'sort64', 28 + ), 29 + self::CONFIG_KEY_SCHEMA => array( 30 + 'key_package' => array( 31 + 'columns' => array('packagePHID', 'name'), 32 + 'unique' => true, 33 + ), 34 + ), 35 + ) + parent::getConfiguration(); 36 + } 37 + 38 + public function generatePHID() { 39 + return PhabricatorPHID::generateNewPHID( 40 + PhabricatorPackagesVersionPHIDType::TYPECONST); 41 + } 42 + 43 + public function getURI() { 44 + $package = $this->getPackage(); 45 + $full_key = $package->getFullKey(); 46 + $name = $this->getName(); 47 + 48 + return "/package/{$full_key}/{$name}/"; 49 + } 50 + 51 + public function attachPackage(PhabricatorPackagesPackage $package) { 52 + $this->package = $package; 53 + return $this; 54 + } 55 + 56 + public function getPackage() { 57 + return $this->assertAttached($this->package); 58 + } 59 + 60 + public static function assertValidVersionName($value) { 61 + $length = phutil_utf8_strlen($value); 62 + if (!$length) { 63 + throw new Exception( 64 + pht( 65 + 'Version name "%s" is not valid: version names are required.', 66 + $value)); 67 + } 68 + 69 + $max_length = 64; 70 + if ($length > $max_length) { 71 + throw new Exception( 72 + pht( 73 + 'Version name "%s" is not valid: version names must not be '. 74 + 'more than %s characters long.', 75 + $value, 76 + new PhutilNumber($max_length))); 77 + } 78 + 79 + if (!preg_match('/^[A-Za-z0-9.-]+\z/', $value)) { 80 + throw new Exception( 81 + pht( 82 + 'Version name "%s" is not valid: version names may only contain '. 83 + 'latin letters, digits, periods, and hyphens.', 84 + $value)); 85 + } 86 + 87 + if (preg_match('/^[.-]|[.-]$/', $value)) { 88 + throw new Exception( 89 + pht( 90 + 'Version name "%s" is not valid: version names may not start or '. 91 + 'end with a period or hyphen.', 92 + $value)); 93 + } 94 + } 95 + 96 + 97 + /* -( PhabricatorSubscribableInterface )----------------------------------- */ 98 + 99 + 100 + public function isAutomaticallySubscribed($phid) { 101 + return false; 102 + } 103 + 104 + 105 + /* -( Policy Interface )--------------------------------------------------- */ 106 + 107 + 108 + public function getCapabilities() { 109 + return array( 110 + PhabricatorPolicyCapability::CAN_VIEW, 111 + PhabricatorPolicyCapability::CAN_EDIT, 112 + ); 113 + } 114 + 115 + public function getPolicy($capability) { 116 + switch ($capability) { 117 + case PhabricatorPolicyCapability::CAN_VIEW: 118 + return PhabricatorPolicies::getMostOpenPolicy(); 119 + case PhabricatorPolicyCapability::CAN_EDIT: 120 + return PhabricatorPolicies::POLICY_USER; 121 + } 122 + } 123 + 124 + public function hasAutomaticCapability($capability, PhabricatorUser $user) { 125 + return false; 126 + } 127 + 128 + public function describeAutomaticCapability($capability) { 129 + return null; 130 + } 131 + 132 + 133 + /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ 134 + 135 + 136 + public function getExtendedPolicy($capability, PhabricatorUser $viewer) { 137 + return array( 138 + array( 139 + $this->getPackage(), 140 + $capability, 141 + ), 142 + ); 143 + } 144 + 145 + 146 + /* -( PhabricatorDestructibleInterface )----------------------------------- */ 147 + 148 + 149 + public function destroyObjectPermanently( 150 + PhabricatorDestructionEngine $engine) { 151 + $this->delete(); 152 + } 153 + 154 + 155 + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 156 + 157 + 158 + public function getApplicationTransactionEditor() { 159 + return new PhabricatorPackagesVersionEditor(); 160 + } 161 + 162 + public function getApplicationTransactionObject() { 163 + return $this; 164 + } 165 + 166 + public function getApplicationTransactionTemplate() { 167 + return new PhabricatorPackagesVersionTransaction(); 168 + } 169 + 170 + public function willRenderTimeline( 171 + PhabricatorApplicationTransactionView $timeline, 172 + AphrontRequest $request) { 173 + return $timeline; 174 + } 175 + 176 + 177 + /* -( PhabricatorConduitResultInterface )---------------------------------- */ 178 + 179 + 180 + public function getFieldSpecificationsForConduit() { 181 + return array( 182 + id(new PhabricatorConduitSearchFieldSpecification()) 183 + ->setKey('name') 184 + ->setType('string') 185 + ->setDescription(pht('The name of the version.')), 186 + ); 187 + } 188 + 189 + public function getFieldValuesForConduit() { 190 + return array( 191 + 'name' => $this->getName(), 192 + ); 193 + } 194 + 195 + public function getConduitSearchAttachments() { 196 + return array(); 197 + } 198 + 199 + 200 + }
+18
src/applications/packages/storage/PhabricatorPackagesVersionTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionTransaction 4 + extends PhabricatorModularTransaction { 5 + 6 + public function getApplicationName() { 7 + return 'packages'; 8 + } 9 + 10 + public function getApplicationTransactionType() { 11 + return PhabricatorPackagesVersionPHIDType::TYPECONST; 12 + } 13 + 14 + public function getBaseTransactionClass() { 15 + return 'PhabricatorPackagesVersionTransactionType'; 16 + } 17 + 18 + }
+35
src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageDatasource 4 + extends PhabricatorTypeaheadDatasource { 5 + 6 + public function getBrowseTitle() { 7 + return pht('Browse Packagess'); 8 + } 9 + 10 + public function getPlaceholderText() { 11 + return pht('Type a package name...'); 12 + } 13 + 14 + public function getDatasourceApplicationClass() { 15 + return 'PhabricatorPackagesApplication'; 16 + } 17 + 18 + public function loadResults() { 19 + $viewer = $this->getViewer(); 20 + $raw_query = $this->getRawQuery(); 21 + 22 + $package_query = id(new PhabricatorPackagesPackageQuery()); 23 + $packages = $this->executeQuery($package_query); 24 + 25 + $results = array(); 26 + foreach ($packages as $package) { 27 + $results[] = id(new PhabricatorTypeaheadResult()) 28 + ->setName($package->getName()) 29 + ->setPHID($package->getPHID()); 30 + } 31 + 32 + return $this->filterResultsAgainstTokens($results); 33 + } 34 + 35 + }
+2 -1
src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
··· 16 16 public function validateTransactions($object, array $xactions) { 17 17 $errors = array(); 18 18 19 - if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 19 + $current_value = $object->getPublisherPHID(); 20 + if ($this->isEmptyTextTransaction($current_value, $xactions)) { 20 21 $errors[] = $this->newRequiredError( 21 22 pht( 22 23 'You must select a publisher when creating a package.'));
+62
src/applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionNameTransaction 4 + extends PhabricatorPackagesVersionTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'packages.version.name'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getName(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setName($value); 14 + } 15 + 16 + public function getTitle() { 17 + return pht( 18 + '%s changed the name of this version from %s to %s.', 19 + $this->renderAuthor(), 20 + $this->renderOldValue(), 21 + $this->renderNewValue()); 22 + } 23 + 24 + public function getTitleForFeed() { 25 + return pht( 26 + '%s updated the name for %s from %s to %s.', 27 + $this->renderAuthor(), 28 + $this->renderObject(), 29 + $this->renderOldValue(), 30 + $this->renderNewValue()); 31 + } 32 + 33 + public function validateTransactions($object, array $xactions) { 34 + $errors = array(); 35 + 36 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 37 + $errors[] = $this->newRequiredError( 38 + pht('Versions must have a name.')); 39 + return $errors; 40 + } 41 + 42 + foreach ($xactions as $xaction) { 43 + $value = $xaction->getNewValue(); 44 + try { 45 + PhabricatorPackagesVersion::assertValidVersionName($value); 46 + } catch (Exception $ex) { 47 + $errors[] = $this->newInvalidError($ex->getMessage(), $xaction); 48 + } 49 + } 50 + 51 + if (!$this->isNewObject()) { 52 + foreach ($xactions as $xaction) { 53 + $errors[] = $this->newInvalidError( 54 + pht('Once a version is created, its name can not be changed.'), 55 + $xaction); 56 + } 57 + } 58 + 59 + return $errors; 60 + } 61 + 62 + }
+66
src/applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesVersionPackageTransaction 4 + extends PhabricatorPackagesVersionTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'packages.version.package'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getPackagePHID(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setPackagePHID($value); 14 + } 15 + 16 + public function validateTransactions($object, array $xactions) { 17 + $errors = array(); 18 + 19 + if ($this->isEmptyTextTransaction($object->getPackagePHID(), $xactions)) { 20 + $errors[] = $this->newRequiredError( 21 + pht( 22 + 'You must select a package when creating a version')); 23 + return $errors; 24 + } 25 + 26 + if (!$this->isNewObject()) { 27 + foreach ($xactions as $xaction) { 28 + $errors[] = $this->newInvalidError( 29 + pht('Once a version is created, its package can not be changed.'), 30 + $xaction); 31 + } 32 + } 33 + 34 + $viewer = $this->getActor(); 35 + foreach ($xactions as $xaction) { 36 + $package_phid = $xaction->getNewValue(); 37 + 38 + $package = id(new PhabricatorPackagesPackageQuery()) 39 + ->setViewer($viewer) 40 + ->withPHIDs(array($package_phid)) 41 + ->setRaisePolicyExceptions(false) 42 + ->requireCapabilities( 43 + array( 44 + PhabricatorPolicyCapability::CAN_VIEW, 45 + PhabricatorPolicyCapability::CAN_EDIT, 46 + )) 47 + ->executeOne(); 48 + 49 + if (!$package) { 50 + $errors[] = $this->newInvalidError( 51 + pht( 52 + 'Package "%s" is invalid: the package must exist and you '. 53 + 'must have permission to edit it in order to create a new '. 54 + 'package.', 55 + $package_phid), 56 + $xaction); 57 + continue; 58 + } 59 + 60 + $object->attachPackage($package); 61 + } 62 + 63 + return $errors; 64 + } 65 + 66 + }
+4
src/applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorPackagesVersionTransactionType 4 + extends PhabricatorPackagesTransactionType {}