@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 PackagesPackage

Summary:
Ref T8116. A package has:

- a publisher (like "Phacility"), from the previous revision;
- a name (like "Arcanist");
- a package key (like "arcanist").

The package key is immutable, like the publisher key.

This gives a package a full key like "phacility/arcanist".

Policy stuff:

- You must be able to view a publisher to view a package (currently, everyone can always see all publishers).
- You must be able to edit a publisher to create a new package inside it.
- Packages have separate view/edit permissions.

This still does nothing interesting.

Test Plan: {F1731663}

Reviewers: chad

Reviewed By: chad

Subscribers: eadler

Maniphest Tasks: T8116

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

+1178 -14
+13
resources/sql/autopatches/20160721.pack.04.pkg.sql
··· 1 + CREATE TABLE {$NAMESPACE}_packages.packages_package ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + phid VARBINARY(64) NOT NULL, 4 + name VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}, 5 + publisherPHID VARBINARY(64) NOT NULL, 6 + packageKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_SORT}, 7 + viewPolicy VARBINARY(64) NOT NULL, 8 + editPolicy VARBINARY(64) NOT NULL, 9 + dateCreated INT UNSIGNED NOT NULL, 10 + dateModified INT UNSIGNED NOT NULL, 11 + UNIQUE KEY `key_phid` (phid), 12 + UNIQUE KEY `key_package` (publisherPHID, packageKey) 13 + ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+19
resources/sql/autopatches/20160721.pack.05.pkgxaction.sql
··· 1 + CREATE TABLE {$NAMESPACE}_packages.packages_packagetransaction ( 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};
+49 -1
src/__phutil_library_map__.php
··· 2977 2977 'PhabricatorPackagesDAO' => 'applications/packages/storage/PhabricatorPackagesDAO.php', 2978 2978 'PhabricatorPackagesEditEngine' => 'applications/packages/editor/PhabricatorPackagesEditEngine.php', 2979 2979 'PhabricatorPackagesEditor' => 'applications/packages/editor/PhabricatorPackagesEditor.php', 2980 + 'PhabricatorPackagesPackage' => 'applications/packages/storage/PhabricatorPackagesPackage.php', 2981 + 'PhabricatorPackagesPackageController' => 'applications/packages/controller/PhabricatorPackagesPackageController.php', 2982 + 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageEditConduitAPIMethod.php', 2983 + 'PhabricatorPackagesPackageEditController' => 'applications/packages/controller/PhabricatorPackagesPackageEditController.php', 2984 + 'PhabricatorPackagesPackageEditEngine' => 'applications/packages/editor/PhabricatorPackagesPackageEditEngine.php', 2985 + 'PhabricatorPackagesPackageEditor' => 'applications/packages/editor/PhabricatorPackagesPackageEditor.php', 2986 + 'PhabricatorPackagesPackageKeyTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackageKeyTransaction.php', 2987 + 'PhabricatorPackagesPackageListController' => 'applications/packages/controller/PhabricatorPackagesPackageListController.php', 2988 + 'PhabricatorPackagesPackageNameTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackageNameTransaction.php', 2989 + 'PhabricatorPackagesPackagePHIDType' => 'applications/packages/phid/PhabricatorPackagesPackagePHIDType.php', 2990 + 'PhabricatorPackagesPackagePublisherTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php', 2991 + 'PhabricatorPackagesPackageQuery' => 'applications/packages/query/PhabricatorPackagesPackageQuery.php', 2992 + 'PhabricatorPackagesPackageSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageSearchConduitAPIMethod.php', 2993 + 'PhabricatorPackagesPackageSearchEngine' => 'applications/packages/query/PhabricatorPackagesPackageSearchEngine.php', 2994 + 'PhabricatorPackagesPackageTransaction' => 'applications/packages/storage/PhabricatorPackagesPackageTransaction.php', 2995 + 'PhabricatorPackagesPackageTransactionQuery' => 'applications/packages/query/PhabricatorPackagesPackageTransactionQuery.php', 2996 + 'PhabricatorPackagesPackageTransactionType' => 'applications/packages/xaction/package/PhabricatorPackagesPackageTransactionType.php', 2997 + 'PhabricatorPackagesPackageViewController' => 'applications/packages/controller/PhabricatorPackagesPackageViewController.php', 2980 2998 'PhabricatorPackagesPublisher' => 'applications/packages/storage/PhabricatorPackagesPublisher.php', 2981 2999 'PhabricatorPackagesPublisherController' => 'applications/packages/controller/PhabricatorPackagesPublisherController.php', 3000 + 'PhabricatorPackagesPublisherDatasource' => 'applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php', 2982 3001 'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPublisherEditConduitAPIMethod.php', 2983 3002 'PhabricatorPackagesPublisherEditController' => 'applications/packages/controller/PhabricatorPackagesPublisherEditController.php', 2984 3003 'PhabricatorPackagesPublisherEditEngine' => 'applications/packages/editor/PhabricatorPackagesPublisherEditEngine.php', ··· 2994 3013 'PhabricatorPackagesPublisherTransactionQuery' => 'applications/packages/query/PhabricatorPackagesPublisherTransactionQuery.php', 2995 3014 'PhabricatorPackagesPublisherTransactionType' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherTransactionType.php', 2996 3015 'PhabricatorPackagesPublisherViewController' => 'applications/packages/controller/PhabricatorPackagesPublisherViewController.php', 3016 + 'PhabricatorPackagesQuery' => 'applications/packages/query/PhabricatorPackagesQuery.php', 2997 3017 'PhabricatorPackagesSchemaSpec' => 'applications/packages/storage/PhabricatorPackagesSchemaSpec.php', 2998 3018 'PhabricatorPackagesTransactionType' => 'applications/packages/xaction/PhabricatorPackagesTransactionType.php', 2999 3019 'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php', ··· 7754 7774 'PhabricatorPackagesDAO' => 'PhabricatorLiskDAO', 7755 7775 'PhabricatorPackagesEditEngine' => 'PhabricatorEditEngine', 7756 7776 'PhabricatorPackagesEditor' => 'PhabricatorApplicationTransactionEditor', 7777 + 'PhabricatorPackagesPackage' => array( 7778 + 'PhabricatorPackagesDAO', 7779 + 'PhabricatorPolicyInterface', 7780 + 'PhabricatorApplicationTransactionInterface', 7781 + 'PhabricatorDestructibleInterface', 7782 + 'PhabricatorSubscribableInterface', 7783 + 'PhabricatorProjectInterface', 7784 + 'PhabricatorConduitResultInterface', 7785 + ), 7786 + 'PhabricatorPackagesPackageController' => 'PhabricatorPackagesController', 7787 + 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 7788 + 'PhabricatorPackagesPackageEditController' => 'PhabricatorPackagesPackageController', 7789 + 'PhabricatorPackagesPackageEditEngine' => 'PhabricatorPackagesEditEngine', 7790 + 'PhabricatorPackagesPackageEditor' => 'PhabricatorPackagesEditor', 7791 + 'PhabricatorPackagesPackageKeyTransaction' => 'PhabricatorPackagesPackageTransactionType', 7792 + 'PhabricatorPackagesPackageListController' => 'PhabricatorPackagesPackageController', 7793 + 'PhabricatorPackagesPackageNameTransaction' => 'PhabricatorPackagesPackageTransactionType', 7794 + 'PhabricatorPackagesPackagePHIDType' => 'PhabricatorPHIDType', 7795 + 'PhabricatorPackagesPackagePublisherTransaction' => 'PhabricatorPackagesPackageTransactionType', 7796 + 'PhabricatorPackagesPackageQuery' => 'PhabricatorPackagesQuery', 7797 + 'PhabricatorPackagesPackageSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 7798 + 'PhabricatorPackagesPackageSearchEngine' => 'PhabricatorApplicationSearchEngine', 7799 + 'PhabricatorPackagesPackageTransaction' => 'PhabricatorModularTransaction', 7800 + 'PhabricatorPackagesPackageTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7801 + 'PhabricatorPackagesPackageTransactionType' => 'PhabricatorPackagesTransactionType', 7802 + 'PhabricatorPackagesPackageViewController' => 'PhabricatorPackagesPackageController', 7757 7803 'PhabricatorPackagesPublisher' => array( 7758 7804 'PhabricatorPackagesDAO', 7759 7805 'PhabricatorPolicyInterface', ··· 7764 7810 'PhabricatorConduitResultInterface', 7765 7811 ), 7766 7812 'PhabricatorPackagesPublisherController' => 'PhabricatorPackagesController', 7813 + 'PhabricatorPackagesPublisherDatasource' => 'PhabricatorTypeaheadDatasource', 7767 7814 'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 7768 7815 'PhabricatorPackagesPublisherEditController' => 'PhabricatorPackagesPublisherController', 7769 7816 'PhabricatorPackagesPublisherEditEngine' => 'PhabricatorPackagesEditEngine', ··· 7772 7819 'PhabricatorPackagesPublisherListController' => 'PhabricatorPackagesPublisherController', 7773 7820 'PhabricatorPackagesPublisherNameTransaction' => 'PhabricatorPackagesPublisherTransactionType', 7774 7821 'PhabricatorPackagesPublisherPHIDType' => 'PhabricatorPHIDType', 7775 - 'PhabricatorPackagesPublisherQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7822 + 'PhabricatorPackagesPublisherQuery' => 'PhabricatorPackagesQuery', 7776 7823 'PhabricatorPackagesPublisherSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 7777 7824 'PhabricatorPackagesPublisherSearchEngine' => 'PhabricatorApplicationSearchEngine', 7778 7825 'PhabricatorPackagesPublisherTransaction' => 'PhabricatorModularTransaction', 7779 7826 'PhabricatorPackagesPublisherTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7780 7827 'PhabricatorPackagesPublisherTransactionType' => 'PhabricatorPackagesTransactionType', 7781 7828 'PhabricatorPackagesPublisherViewController' => 'PhabricatorPackagesPublisherController', 7829 + 'PhabricatorPackagesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7782 7830 'PhabricatorPackagesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 7783 7831 'PhabricatorPackagesTransactionType' => 'PhabricatorModularTransactionType', 7784 7832 'PhabricatorPagerUIExample' => 'PhabricatorUIExample',
+9
src/applications/packages/application/PhabricatorPackagesApplication.php
··· 31 31 '/package/' => array( 32 32 '(?P<publisherKey>[^/]+)/' => array( 33 33 '' => 'PhabricatorPackagesPublisherViewController', 34 + '(?P<packageKey>[^/]+)/' => array( 35 + '' => 'PhabricatorPackagesPackageViewController', 36 + ), 34 37 ), 35 38 ), 36 39 '/packages/' => array( ··· 39 42 'PhabricatorPackagesPublisherListController', 40 43 $this->getEditRoutePattern('edit/') => 41 44 'PhabricatorPackagesPublisherEditController', 45 + ), 46 + 'package/' => array( 47 + $this->getQueryRoutePattern() => 48 + 'PhabricatorPackagesPackageListController', 49 + $this->getEditRoutePattern('edit/') => 50 + 'PhabricatorPackagesPackageEditController', 42 51 ), 43 52 ), 44 53 );
+19
src/applications/packages/conduit/PhabricatorPackagesPackageEditConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageEditConduitAPIMethod 4 + extends PhabricatorEditEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'packages.package.edit'; 8 + } 9 + 10 + public function newEditEngine() { 11 + return new PhabricatorPackagesPackageEditEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht( 16 + 'Apply transactions to create a new package or edit an existing one.'); 17 + } 18 + 19 + }
+18
src/applications/packages/conduit/PhabricatorPackagesPackageSearchConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageSearchConduitAPIMethod 4 + extends PhabricatorSearchEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'packages.package.search'; 8 + } 9 + 10 + public function newSearchEngine() { 11 + return new PhabricatorPackagesPackageSearchEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht('Read information about packages.'); 16 + } 17 + 18 + }
+4
src/applications/packages/controller/PhabricatorPackagesPackageController.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorPackagesPackageController 4 + extends PhabricatorPackagesController {}
+12
src/applications/packages/controller/PhabricatorPackagesPackageEditController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageEditController 4 + extends PhabricatorPackagesPackageController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + return id(new PhabricatorPackagesPackageEditEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 10 + } 11 + 12 + }
+26
src/applications/packages/controller/PhabricatorPackagesPackageListController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageListController 4 + extends PhabricatorPackagesPackageController { 5 + 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + return id(new PhabricatorPackagesPackageSearchEngine()) 12 + ->setController($this) 13 + ->buildResponse(); 14 + } 15 + 16 + protected function buildApplicationCrumbs() { 17 + $crumbs = parent::buildApplicationCrumbs(); 18 + 19 + id(new PhabricatorPackagesPackageEditEngine()) 20 + ->setViewer($this->getViewer()) 21 + ->addActionToCrumbs($crumbs); 22 + 23 + return $crumbs; 24 + } 25 + 26 + }
+87
src/applications/packages/controller/PhabricatorPackagesPackageViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageViewController 4 + extends PhabricatorPackagesPackageController { 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 + 17 + $package = id(new PhabricatorPackagesPackageQuery()) 18 + ->setViewer($viewer) 19 + ->withFullKeys(array($full_key)) 20 + ->executeOne(); 21 + if (!$package) { 22 + return new Aphront404Response(); 23 + } 24 + 25 + $publisher = $package->getPublisher(); 26 + 27 + $crumbs = $this->buildApplicationCrumbs() 28 + ->addTextCrumb($publisher->getName(), $publisher->getURI()) 29 + ->addTextCrumb($package->getName()) 30 + ->setBorder(true); 31 + 32 + $header = $this->buildHeaderView($package); 33 + $curtain = $this->buildCurtain($package); 34 + 35 + $timeline = $this->buildTransactionTimeline( 36 + $package, 37 + new PhabricatorPackagesPackageTransactionQuery()); 38 + 39 + $package_view = id(new PHUITwoColumnView()) 40 + ->setHeader($header) 41 + ->setCurtain($curtain) 42 + ->setMainColumn($timeline); 43 + 44 + return $this->newPage() 45 + ->setCrumbs($crumbs) 46 + ->setPageObjectPHIDs( 47 + array( 48 + $package->getPHID(), 49 + )) 50 + ->appendChild($package_view); 51 + } 52 + 53 + 54 + private function buildHeaderView(PhabricatorPackagesPackage $package) { 55 + $viewer = $this->getViewer(); 56 + $name = $package->getName(); 57 + 58 + return id(new PHUIHeaderView()) 59 + ->setViewer($viewer) 60 + ->setHeader($name) 61 + ->setPolicyObject($package) 62 + ->setHeaderIcon('fa-gift'); 63 + } 64 + 65 + private function buildCurtain(PhabricatorPackagesPackage $package) { 66 + $viewer = $this->getViewer(); 67 + $curtain = $this->newCurtainView($package); 68 + 69 + $can_edit = PhabricatorPolicyFilter::hasCapability( 70 + $viewer, 71 + $package, 72 + PhabricatorPolicyCapability::CAN_EDIT); 73 + 74 + $id = $package->getID(); 75 + $edit_uri = $this->getApplicationURI("package/edit/{$id}/"); 76 + 77 + $curtain->addAction( 78 + id(new PhabricatorActionView()) 79 + ->setName(pht('Edit Package')) 80 + ->setIcon('fa-pencil') 81 + ->setDisabled(!$can_edit) 82 + ->setHref($edit_uri)); 83 + 84 + return $curtain; 85 + } 86 + 87 + }
+104
src/applications/packages/editor/PhabricatorPackagesPackageEditEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageEditEngine 4 + extends PhabricatorPackagesEditEngine { 5 + 6 + const ENGINECONST = 'packages.package'; 7 + 8 + public function getEngineName() { 9 + return pht('Package Packages'); 10 + } 11 + 12 + public function getSummaryHeader() { 13 + return pht('Edit Package Package Configurations'); 14 + } 15 + 16 + public function getSummaryText() { 17 + return pht('This engine is used to edit Packages packages.'); 18 + } 19 + 20 + protected function newEditableObject() { 21 + $viewer = $this->getViewer(); 22 + return PhabricatorPackagesPackage::initializeNewPackage($viewer); 23 + } 24 + 25 + protected function newObjectQuery() { 26 + return new PhabricatorPackagesPackageQuery(); 27 + } 28 + 29 + protected function getObjectCreateTitleText($object) { 30 + return pht('Create Package'); 31 + } 32 + 33 + protected function getObjectCreateButtonText($object) { 34 + return pht('Create Package'); 35 + } 36 + 37 + protected function getObjectEditTitleText($object) { 38 + return pht('Edit Package: %s', $object->getName()); 39 + } 40 + 41 + protected function getObjectEditShortText($object) { 42 + return pht('Edit Package'); 43 + } 44 + 45 + protected function getObjectCreateShortText() { 46 + return pht('Create Package'); 47 + } 48 + 49 + protected function getObjectName() { 50 + return pht('Package'); 51 + } 52 + 53 + protected function getEditorURI() { 54 + return '/packages/package/edit/'; 55 + } 56 + 57 + protected function getObjectCreateCancelURI($object) { 58 + return '/packages/package/'; 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('publisher') 71 + ->setAliases(array('publisherPHID')) 72 + ->setLabel(pht('Publisher')) 73 + ->setDescription(pht('Publisher for this package.')) 74 + ->setTransactionType( 75 + PhabricatorPackagesPackagePublisherTransaction::TRANSACTIONTYPE) 76 + ->setIsRequired(true) 77 + ->setDatasource(new PhabricatorPackagesPublisherDatasource()) 78 + ->setSingleValue($object->getPublisherPHID()); 79 + } 80 + 81 + $fields[] = id(new PhabricatorTextEditField()) 82 + ->setKey('name') 83 + ->setLabel(pht('Name')) 84 + ->setDescription(pht('Name of the package.')) 85 + ->setTransactionType( 86 + PhabricatorPackagesPackageNameTransaction::TRANSACTIONTYPE) 87 + ->setIsRequired(true) 88 + ->setValue($object->getName()); 89 + 90 + if ($this->getIsCreate()) { 91 + $fields[] = id(new PhabricatorTextEditField()) 92 + ->setKey('packageKey') 93 + ->setLabel(pht('Package Key')) 94 + ->setDescription(pht('Unique key to identify the package.')) 95 + ->setTransactionType( 96 + PhabricatorPackagesPackageKeyTransaction::TRANSACTIONTYPE) 97 + ->setIsRequired(true) 98 + ->setValue($object->getPackageKey()); 99 + } 100 + 101 + return $fields; 102 + } 103 + 104 + }
+55
src/applications/packages/editor/PhabricatorPackagesPackageEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageEditor 4 + extends PhabricatorPackagesEditor { 5 + 6 + public function getEditorObjectsDescription() { 7 + return pht('Package Packages'); 8 + } 9 + 10 + public function getCreateObjectTitle($author, $object) { 11 + return pht('%s created this package.', $author); 12 + } 13 + 14 + public function getCreateObjectTitleForFeed($author, $object) { 15 + return pht('%s created %s.', $author, $object); 16 + } 17 + 18 + public function getTransactionTypes() { 19 + $types = parent::getTransactionTypes(); 20 + 21 + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 22 + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 23 + 24 + return $types; 25 + } 26 + 27 + protected function shouldPublishFeedStory( 28 + PhabricatorLiskDAO $object, 29 + array $xactions) { 30 + return true; 31 + } 32 + 33 + protected function getMailTo(PhabricatorLiskDAO $object) { 34 + return array(); 35 + } 36 + 37 + protected function didCatchDuplicateKeyException( 38 + PhabricatorLiskDAO $object, 39 + array $xactions, 40 + Exception $ex) { 41 + 42 + $errors = array(); 43 + $errors[] = new PhabricatorApplicationTransactionValidationError( 44 + PhabricatorPackagesPackageKeyTransaction::TRANSACTIONTYPE, 45 + pht('Duplicate'), 46 + pht( 47 + 'The package key "%s" is already in use by another package provided '. 48 + 'by this publisher.', 49 + $object->getPackageKey()), 50 + null); 51 + 52 + throw new PhabricatorApplicationTransactionValidationException($errors); 53 + } 54 + 55 + }
+7 -7
src/applications/packages/editor/PhabricatorPackagesPublisherEditEngine.php
··· 76 76 77 77 if ($this->getIsCreate()) { 78 78 $fields[] = id(new PhabricatorTextEditField()) 79 - ->setKey('publisherKey') 80 - ->setLabel(pht('Publisher Key')) 81 - ->setDescription(pht('Unique key to identify the publisher.')) 82 - ->setTransactionType( 83 - PhabricatorPackagesPublisherKeyTransaction::TRANSACTIONTYPE) 84 - ->setIsRequired(true) 85 - ->setValue($object->getPublisherKey()); 79 + ->setKey('publisherKey') 80 + ->setLabel(pht('Publisher Key')) 81 + ->setDescription(pht('Unique key to identify the publisher.')) 82 + ->setTransactionType( 83 + PhabricatorPackagesPublisherKeyTransaction::TRANSACTIONTYPE) 84 + ->setIsRequired(true) 85 + ->setValue($object->getPublisherKey()); 86 86 } 87 87 88 88 return $fields;
+45
src/applications/packages/phid/PhabricatorPackagesPackagePHIDType.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackagePHIDType 4 + extends PhabricatorPHIDType { 5 + 6 + const TYPECONST = 'PPAK'; 7 + 8 + public function getTypeName() { 9 + return pht('Package'); 10 + } 11 + 12 + public function newObject() { 13 + return new PhabricatorPackagesPackage(); 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 PhabricatorPackagesPackageQuery()) 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 + $package = $objects[$phid]; 35 + 36 + $name = $package->getName(); 37 + $uri = $package->getURI(); 38 + 39 + $handle 40 + ->setName($name) 41 + ->setURI($uri); 42 + } 43 + } 44 + 45 + }
+152
src/applications/packages/query/PhabricatorPackagesPackageQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageQuery 4 + extends PhabricatorPackagesQuery { 5 + 6 + private $ids; 7 + private $phids; 8 + private $publisherPHIDs; 9 + private $packageKeys; 10 + private $fullKeys; 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 withPublisherPHIDs(array $phids) { 23 + $this->publisherPHIDs = $phids; 24 + return $this; 25 + } 26 + 27 + public function withPackageKeys(array $keys) { 28 + $this->packageKeys = $keys; 29 + return $this; 30 + } 31 + 32 + public function withFullKeys(array $keys) { 33 + $this->fullKeys = $keys; 34 + return $this; 35 + } 36 + 37 + public function newResultObject() { 38 + return new PhabricatorPackagesPackage(); 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 + 'p.id IN (%Ld)', 52 + $this->ids); 53 + } 54 + 55 + if ($this->phids !== null) { 56 + $where[] = qsprintf( 57 + $conn, 58 + 'p.phid IN (%Ls)', 59 + $this->phids); 60 + } 61 + 62 + if ($this->publisherPHIDs !== null) { 63 + $where[] = qsprintf( 64 + $conn, 65 + 'p.phid IN (%Ls)', 66 + $this->publisherPHIDs); 67 + } 68 + 69 + if ($this->packageKeys !== null) { 70 + $where[] = qsprintf( 71 + $conn, 72 + 'p.packageKey IN (%Ls)', 73 + $this->packageKeys); 74 + } 75 + 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)); 102 + } 103 + 104 + return $where; 105 + } 106 + 107 + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { 108 + $joins = parent::buildJoinClauseParts($conn); 109 + 110 + $join_publisher = ($this->fullKeys !== null); 111 + if ($join_publisher) { 112 + $publisher_table = new PhabricatorPackagesPublisher(); 113 + 114 + $joins[] = qsprintf( 115 + $conn, 116 + 'JOIN %T u ON u.phid = p.publisherPHID', 117 + $publisher_table->getTableName()); 118 + } 119 + 120 + return $joins; 121 + } 122 + 123 + protected function willFilterPage(array $packages) { 124 + $publisher_phids = mpull($packages, 'getPublisherPHID'); 125 + 126 + $publishers = id(new PhabricatorPackagesPublisherQuery()) 127 + ->setViewer($this->getViewer()) 128 + ->setParentQuery($this) 129 + ->withPHIDs($publisher_phids) 130 + ->execute(); 131 + $publishers = mpull($publishers, null, 'getPHID'); 132 + 133 + foreach ($packages as $key => $package) { 134 + $publisher = idx($publishers, $package->getPublisherPHID()); 135 + 136 + if (!$publisher) { 137 + unset($packages[$key]); 138 + $this->didRejectResult($package); 139 + continue; 140 + } 141 + 142 + $package->attachPublisher($publisher); 143 + } 144 + 145 + return $packages; 146 + } 147 + 148 + protected function getPrimaryTableAlias() { 149 + return 'p'; 150 + } 151 + 152 + }
+77
src/applications/packages/query/PhabricatorPackagesPackageSearchEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageSearchEngine 4 + extends PhabricatorApplicationSearchEngine { 5 + 6 + public function getResultTypeDescription() { 7 + return pht('Packages'); 8 + } 9 + 10 + public function getApplicationClassName() { 11 + return 'PhabricatorPackagesApplication'; 12 + } 13 + 14 + public function newQuery() { 15 + return id(new PhabricatorPackagesPackageQuery()); 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/package/'.$path; 30 + } 31 + 32 + protected function getBuiltinQueryNames() { 33 + $names = array( 34 + 'all' => pht('All Packages'), 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 $packages, 54 + PhabricatorSavedQuery $query, 55 + array $handles) { 56 + 57 + assert_instances_of($packages, 'PhabricatorPackagesPackage'); 58 + 59 + $viewer = $this->requireViewer(); 60 + 61 + $list = id(new PHUIObjectItemListView()) 62 + ->setViewer($viewer); 63 + foreach ($packages as $package) { 64 + $item = id(new PHUIObjectItemView()) 65 + ->setObjectName($package->getFullKey()) 66 + ->setHeader($package->getName()) 67 + ->setHref($package->getURI()); 68 + 69 + $list->addItem($item); 70 + } 71 + 72 + return id(new PhabricatorApplicationSearchResultView()) 73 + ->setObjectList($list) 74 + ->setNoDataString(pht('No packages found.')); 75 + } 76 + 77 + }
+10
src/applications/packages/query/PhabricatorPackagesPackageTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + public function getTemplateApplicationTransaction() { 7 + return new PhabricatorPackagesPackageTransaction(); 8 + } 9 + 10 + }
+1 -5
src/applications/packages/query/PhabricatorPackagesPublisherQuery.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorPackagesPublisherQuery 4 - extends PhabricatorCursorPagedPolicyAwareQuery { 4 + extends PhabricatorPackagesQuery { 5 5 6 6 private $ids; 7 7 private $phids; ··· 55 55 } 56 56 57 57 return $where; 58 - } 59 - 60 - public function getQueryApplicationClass() { 61 - return 'PhabricatorPackagesApplication'; 62 58 } 63 59 64 60 }
+10
src/applications/packages/query/PhabricatorPackagesQuery.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorPackagesQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + public function getQueryApplicationClass() { 7 + return 'PhabricatorPackagesApplication'; 8 + } 9 + 10 + }
+222
src/applications/packages/storage/PhabricatorPackagesPackage.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackage 4 + extends PhabricatorPackagesDAO 5 + implements 6 + PhabricatorPolicyInterface, 7 + PhabricatorApplicationTransactionInterface, 8 + PhabricatorDestructibleInterface, 9 + PhabricatorSubscribableInterface, 10 + PhabricatorProjectInterface, 11 + PhabricatorConduitResultInterface { 12 + 13 + protected $name; 14 + protected $publisherPHID; 15 + protected $packageKey; 16 + protected $viewPolicy; 17 + protected $editPolicy; 18 + 19 + private $publisher = self::ATTACHABLE; 20 + 21 + public static function initializeNewPackage(PhabricatorUser $actor) { 22 + return id(new self()); 23 + } 24 + 25 + protected function getConfiguration() { 26 + return array( 27 + self::CONFIG_AUX_PHID => true, 28 + self::CONFIG_COLUMN_SCHEMA => array( 29 + 'name' => 'text64', 30 + 'packageKey' => 'sort64', 31 + ), 32 + self::CONFIG_KEY_SCHEMA => array( 33 + 'key_package' => array( 34 + 'columns' => array('publisherPHID', 'packageKey'), 35 + 'unique' => true, 36 + ), 37 + ), 38 + ) + parent::getConfiguration(); 39 + } 40 + 41 + public function generatePHID() { 42 + return PhabricatorPHID::generateNewPHID( 43 + PhabricatorPackagesPackagePHIDType::TYPECONST); 44 + } 45 + 46 + public function getURI() { 47 + $full_key = $this->getFullKey(); 48 + return "/package/{$full_key}/"; 49 + } 50 + 51 + public function getFullKey() { 52 + $publisher = $this->getPublisher(); 53 + $publisher_key = $publisher->getPublisherKey(); 54 + $package_key = $this->getPackageKey(); 55 + return "{$publisher_key}/{$package_key}"; 56 + } 57 + 58 + public function attachPublisher(PhabricatorPackagesPublisher $publisher) { 59 + $this->publisher = $publisher; 60 + return $this; 61 + } 62 + 63 + public function getPublisher() { 64 + return $this->assertAttached($this->publisher); 65 + } 66 + 67 + public static function assertValidPackageName($value) { 68 + $length = phutil_utf8_strlen($value); 69 + if (!$length) { 70 + throw new Exception( 71 + pht( 72 + 'Package name "%s" is not valid: package names are required.', 73 + $value)); 74 + } 75 + 76 + $max_length = 64; 77 + if ($length > $max_length) { 78 + throw new Exception( 79 + pht( 80 + 'Package name "%s" is not valid: package names must not be '. 81 + 'more than %s characters long.', 82 + $value, 83 + new PhutilNumber($max_length))); 84 + } 85 + } 86 + 87 + public static function assertValidPackageKey($value) { 88 + $length = phutil_utf8_strlen($value); 89 + if (!$length) { 90 + throw new Exception( 91 + pht( 92 + 'Package key "%s" is not valid: package keys are required.', 93 + $value)); 94 + } 95 + 96 + $max_length = 64; 97 + if ($length > $max_length) { 98 + throw new Exception( 99 + pht( 100 + 'Package key "%s" is not valid: package keys must not be '. 101 + 'more than %s characters long.', 102 + $value, 103 + new PhutilNumber($max_length))); 104 + } 105 + 106 + if (!preg_match('/^[a-z]+\z/', $value)) { 107 + throw new Exception( 108 + pht( 109 + 'Package key "%s" is not valid: package keys may only contain '. 110 + 'lowercase latin letters.', 111 + $value)); 112 + } 113 + } 114 + 115 + 116 + /* -( PhabricatorSubscribableInterface )----------------------------------- */ 117 + 118 + 119 + public function isAutomaticallySubscribed($phid) { 120 + return false; 121 + } 122 + 123 + 124 + /* -( Policy Interface )--------------------------------------------------- */ 125 + 126 + 127 + public function getCapabilities() { 128 + return array( 129 + PhabricatorPolicyCapability::CAN_VIEW, 130 + PhabricatorPolicyCapability::CAN_EDIT, 131 + ); 132 + } 133 + 134 + public function getPolicy($capability) { 135 + switch ($capability) { 136 + case PhabricatorPolicyCapability::CAN_VIEW: 137 + return $this->getViewPolicy(); 138 + case PhabricatorPolicyCapability::CAN_EDIT: 139 + return $this->getEditPolicy(); 140 + } 141 + } 142 + 143 + public function hasAutomaticCapability($capability, PhabricatorUser $user) { 144 + return false; 145 + } 146 + 147 + public function describeAutomaticCapability($capability) { 148 + return null; 149 + } 150 + 151 + 152 + /* -( PhabricatorDestructibleInterface )----------------------------------- */ 153 + 154 + 155 + public function destroyObjectPermanently( 156 + PhabricatorDestructionEngine $engine) { 157 + $this->delete(); 158 + } 159 + 160 + 161 + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 162 + 163 + 164 + public function getApplicationTransactionEditor() { 165 + return new PhabricatorPackagesPackageEditor(); 166 + } 167 + 168 + public function getApplicationTransactionObject() { 169 + return $this; 170 + } 171 + 172 + public function getApplicationTransactionTemplate() { 173 + return new PhabricatorPackagesPackageTransaction(); 174 + } 175 + 176 + public function willRenderTimeline( 177 + PhabricatorApplicationTransactionView $timeline, 178 + AphrontRequest $request) { 179 + return $timeline; 180 + } 181 + 182 + 183 + /* -( PhabricatorConduitResultInterface )---------------------------------- */ 184 + 185 + 186 + public function getFieldSpecificationsForConduit() { 187 + return array( 188 + id(new PhabricatorConduitSearchFieldSpecification()) 189 + ->setKey('name') 190 + ->setType('string') 191 + ->setDescription(pht('The name of the package.')), 192 + id(new PhabricatorConduitSearchFieldSpecification()) 193 + ->setKey('packageKey') 194 + ->setType('string') 195 + ->setDescription(pht('The unique key of the package.')), 196 + ); 197 + } 198 + 199 + public function getFieldValuesForConduit() { 200 + $publisher = $this->getPublisher(); 201 + 202 + $publisher_map = array( 203 + 'id' => (int)$publisher->getID(), 204 + 'phid' => $publisher->getPHID(), 205 + 'name' => $publisher->getName(), 206 + 'publisherKey' => $publisher->getPublisherKey(), 207 + ); 208 + 209 + return array( 210 + 'name' => $this->getName(), 211 + 'packageKey' => $this->getPackageKey(), 212 + 'fullKey' => $this->getFullKey(), 213 + 'publisher' => $publisher_map, 214 + ); 215 + } 216 + 217 + public function getConduitSearchAttachments() { 218 + return array(); 219 + } 220 + 221 + 222 + }
+18
src/applications/packages/storage/PhabricatorPackagesPackageTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageTransaction 4 + extends PhabricatorModularTransaction { 5 + 6 + public function getApplicationName() { 7 + return 'packages'; 8 + } 9 + 10 + public function getApplicationTransactionType() { 11 + return PhabricatorPackagesPackagePHIDType::TYPECONST; 12 + } 13 + 14 + public function getBaseTransactionClass() { 15 + return 'PhabricatorPackagesPackageTransactionType'; 16 + } 17 + 18 + }
+15 -1
src/applications/packages/storage/PhabricatorPackagesPublisher.php
··· 134 134 135 135 public function destroyObjectPermanently( 136 136 PhabricatorDestructionEngine $engine) { 137 - $this->delete(); 137 + $viewer = $engine->getViewer(); 138 + 139 + $this->openTransaction(); 140 + 141 + $packages = id(new PhabricatorPackagesPackageQuery()) 142 + ->setViewer($viewer) 143 + ->withPublisherPHIDs(array($this->getPHID())) 144 + ->execute(); 145 + foreach ($packages as $package) { 146 + $engine->destroyObject($package); 147 + } 148 + 149 + $this->delete(); 150 + 151 + $this->saveTransaction(); 138 152 } 139 153 140 154
+35
src/applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPublisherDatasource 4 + extends PhabricatorTypeaheadDatasource { 5 + 6 + public function getBrowseTitle() { 7 + return pht('Browse Package Publishers'); 8 + } 9 + 10 + public function getPlaceholderText() { 11 + return pht('Type a publisher 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 + $publisher_query = id(new PhabricatorPackagesPublisherQuery()); 23 + $publishers = $this->executeQuery($publisher_query); 24 + 25 + $results = array(); 26 + foreach ($publishers as $publisher) { 27 + $results[] = id(new PhabricatorTypeaheadResult()) 28 + ->setName($publisher->getName()) 29 + ->setPHID($publisher->getPHID()); 30 + } 31 + 32 + return $this->filterResultsAgainstTokens($results); 33 + } 34 + 35 + }
+47
src/applications/packages/xaction/package/PhabricatorPackagesPackageKeyTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageKeyTransaction 4 + extends PhabricatorPackagesPackageTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'packages.package.key'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getPackageKey(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setPackageKey($value); 14 + } 15 + 16 + public function validateTransactions($object, array $xactions) { 17 + $errors = array(); 18 + 19 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 20 + $errors[] = $this->newRequiredError( 21 + pht( 22 + 'Each package provided by a publisher must have a '. 23 + 'unique package key.')); 24 + return $errors; 25 + } 26 + 27 + if (!$this->isNewObject()) { 28 + foreach ($xactions as $xaction) { 29 + $errors[] = $this->newInvalidError( 30 + pht('Once a package is created, its key can not be changed.'), 31 + $xaction); 32 + } 33 + } 34 + 35 + foreach ($xactions as $xaction) { 36 + $value = $xaction->getNewValue(); 37 + try { 38 + PhabricatorPackagesPackage::assertValidPackageKey($value); 39 + } catch (Exception $ex) { 40 + $errors[] = $this->newInvalidError($ex->getMessage(), $xaction); 41 + } 42 + } 43 + 44 + return $errors; 45 + } 46 + 47 + }
+54
src/applications/packages/xaction/package/PhabricatorPackagesPackageNameTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackageNameTransaction 4 + extends PhabricatorPackagesPackageTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'packages.package.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 package 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('Packages must have a name.')); 39 + return $errors; 40 + } 41 + 42 + foreach ($xactions as $xaction) { 43 + $value = $xaction->getNewValue(); 44 + try { 45 + PhabricatorPackagesPackage::assertValidPackageName($value); 46 + } catch (Exception $ex) { 47 + $errors[] = $this->newInvalidError($ex->getMessage(), $xaction); 48 + } 49 + } 50 + 51 + return $errors; 52 + } 53 + 54 + }
+66
src/applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorPackagesPackagePublisherTransaction 4 + extends PhabricatorPackagesPackageTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'packages.package.publisher'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getPublisherPHID(); 10 + } 11 + 12 + public function applyInternalEffects($object, $value) { 13 + $object->setPublisherPHID($value); 14 + } 15 + 16 + public function validateTransactions($object, array $xactions) { 17 + $errors = array(); 18 + 19 + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { 20 + $errors[] = $this->newRequiredError( 21 + pht( 22 + 'You must select a publisher when creating a package.')); 23 + return $errors; 24 + } 25 + 26 + if (!$this->isNewObject()) { 27 + foreach ($xactions as $xaction) { 28 + $errors[] = $this->newInvalidError( 29 + pht('Once a package is created, its publisher can not be changed.'), 30 + $xaction); 31 + } 32 + } 33 + 34 + $viewer = $this->getActor(); 35 + foreach ($xactions as $xaction) { 36 + $publisher_phid = $xaction->getNewValue(); 37 + 38 + $publisher = id(new PhabricatorPackagesPublisherQuery()) 39 + ->setViewer($viewer) 40 + ->withPHIDs(array($publisher_phid)) 41 + ->setRaisePolicyExceptions(false) 42 + ->requireCapabilities( 43 + array( 44 + PhabricatorPolicyCapability::CAN_VIEW, 45 + PhabricatorPolicyCapability::CAN_EDIT, 46 + )) 47 + ->executeOne(); 48 + 49 + if (!$publisher) { 50 + $errors[] = $this->newInvalidError( 51 + pht( 52 + 'Publisher "%s" is invalid: the publisher must exist and you '. 53 + 'must have permission to edit it in order to create a new '. 54 + 'package.', 55 + $publisher_phid), 56 + $xaction); 57 + continue; 58 + } 59 + 60 + $object->attachPublisher($publisher); 61 + } 62 + 63 + return $errors; 64 + } 65 + 66 + }
+4
src/applications/packages/xaction/package/PhabricatorPackagesPackageTransactionType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorPackagesPackageTransactionType 4 + extends PhabricatorPackagesTransactionType {}