1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 13:30:55 +01:00

Remove the "Phragment" application

Summary:
Ref T5479. Ref T13658. This was a contributed application from the early days of Phabricator which never had customers or users in the wild. The contributor moved on from the project many years ago.

Any capabilities in this general role would look different today. It also has one or two product name literal strings, so this is as good a time as any to remove it.

This change does not remove storage; I'll issue upgrade guidance and do that separately after some time.

Test Plan: Grepped for "phragment", got no relevant hits.

Subscribers: hach-que, PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13658, T5479

Differential Revision: https://secure.phabricator.com/D21793
This commit is contained in:
epriestley 2022-04-25 16:41:47 -07:00
parent 84b0c5a669
commit c415622923
39 changed files with 0 additions and 5846 deletions

File diff suppressed because it is too large Load diff

View file

@ -7552,113 +7552,6 @@ CREATE TABLE `phortune_subscription` (
KEY `key_merchant` (`merchantPHID`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_phragment` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */;
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `edge` (
`src` varbinary(64) NOT NULL,
`type` int(10) unsigned NOT NULL,
`dst` varbinary(64) NOT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`seq` int(10) unsigned NOT NULL,
`dataID` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`src`,`type`,`dst`),
UNIQUE KEY `key_dst` (`dst`,`type`,`src`),
KEY `src` (`src`,`type`,`dateCreated`,`seq`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `edgedata` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`data` longtext CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `phragment_fragment` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`phid` varbinary(64) NOT NULL,
`path` varchar(128) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`depth` int(10) unsigned NOT NULL,
`latestVersionPHID` varbinary(64) DEFAULT NULL,
`viewPolicy` varbinary(64) NOT NULL,
`editPolicy` varbinary(64) NOT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_phid` (`phid`),
UNIQUE KEY `key_path` (`path`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `phragment_fragmentversion` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`phid` varbinary(64) NOT NULL,
`sequence` int(10) unsigned NOT NULL,
`fragmentPHID` varbinary(64) NOT NULL,
`filePHID` varbinary(64) DEFAULT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_version` (`fragmentPHID`,`sequence`),
UNIQUE KEY `key_phid` (`phid`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `phragment_snapshot` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`phid` varbinary(64) NOT NULL,
`primaryFragmentPHID` varbinary(64) NOT NULL,
`name` varchar(128) CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} NOT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_phid` (`phid`),
UNIQUE KEY `key_name` (`primaryFragmentPHID`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
USE `{$NAMESPACE}_phragment`;
SET NAMES utf8 ;
SET character_set_client = {$CHARSET} ;
CREATE TABLE `phragment_snapshotchild` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`snapshotPHID` varbinary(64) NOT NULL,
`fragmentPHID` varbinary(64) NOT NULL,
`fragmentVersionPHID` varbinary(64) DEFAULT NULL,
`dateCreated` int(10) unsigned NOT NULL,
`dateModified` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_child` (`snapshotPHID`,`fragmentPHID`,`fragmentVersionPHID`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `{$NAMESPACE}_phrequent` /*!40100 DEFAULT CHARACTER SET {$CHARSET} COLLATE {$COLLATE_TEXT} */;
USE `{$NAMESPACE}_phrequent`;

View file

@ -1536,7 +1536,6 @@ phutil_register_library_map(array(
'HarbormasterPlanRunController' => 'applications/harbormaster/controller/HarbormasterPlanRunController.php',
'HarbormasterPlanViewController' => 'applications/harbormaster/controller/HarbormasterPlanViewController.php',
'HarbormasterPrototypeBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterPrototypeBuildStepGroup.php',
'HarbormasterPublishFragmentBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php',
'HarbormasterQueryAutotargetsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryAutotargetsConduitAPIMethod.php',
'HarbormasterQueryBuildablesConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildablesConduitAPIMethod.php',
'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php',
@ -4234,7 +4233,6 @@ phutil_register_library_map(array(
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php',
'PhabricatorPhortuneManagementWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementWorkflow.php',
'PhabricatorPhortuneTestCase' => 'applications/phortune/__tests__/PhabricatorPhortuneTestCase.php',
'PhabricatorPhragmentApplication' => 'applications/phragment/application/PhabricatorPhragmentApplication.php',
'PhabricatorPhrequentApplication' => 'applications/phrequent/application/PhabricatorPhrequentApplication.php',
'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php',
'PhabricatorPhurlApplication' => 'applications/phurl/application/PhabricatorPhurlApplication.php',
@ -5559,38 +5557,6 @@ phutil_register_library_map(array(
'PhortuneSubscriptionTransactionType' => 'applications/phortune/xaction/subscription/PhortuneSubscriptionTransactionType.php',
'PhortuneSubscriptionWorker' => 'applications/phortune/worker/PhortuneSubscriptionWorker.php',
'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php',
'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php',
'PhragmentCanCreateCapability' => 'applications/phragment/capability/PhragmentCanCreateCapability.php',
'PhragmentConduitAPIMethod' => 'applications/phragment/conduit/PhragmentConduitAPIMethod.php',
'PhragmentController' => 'applications/phragment/controller/PhragmentController.php',
'PhragmentCreateController' => 'applications/phragment/controller/PhragmentCreateController.php',
'PhragmentDAO' => 'applications/phragment/storage/PhragmentDAO.php',
'PhragmentFragment' => 'applications/phragment/storage/PhragmentFragment.php',
'PhragmentFragmentPHIDType' => 'applications/phragment/phid/PhragmentFragmentPHIDType.php',
'PhragmentFragmentQuery' => 'applications/phragment/query/PhragmentFragmentQuery.php',
'PhragmentFragmentVersion' => 'applications/phragment/storage/PhragmentFragmentVersion.php',
'PhragmentFragmentVersionPHIDType' => 'applications/phragment/phid/PhragmentFragmentVersionPHIDType.php',
'PhragmentFragmentVersionQuery' => 'applications/phragment/query/PhragmentFragmentVersionQuery.php',
'PhragmentGetPatchConduitAPIMethod' => 'applications/phragment/conduit/PhragmentGetPatchConduitAPIMethod.php',
'PhragmentHistoryController' => 'applications/phragment/controller/PhragmentHistoryController.php',
'PhragmentPatchController' => 'applications/phragment/controller/PhragmentPatchController.php',
'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php',
'PhragmentPolicyController' => 'applications/phragment/controller/PhragmentPolicyController.php',
'PhragmentQueryFragmentsConduitAPIMethod' => 'applications/phragment/conduit/PhragmentQueryFragmentsConduitAPIMethod.php',
'PhragmentRevertController' => 'applications/phragment/controller/PhragmentRevertController.php',
'PhragmentSchemaSpec' => 'applications/phragment/storage/PhragmentSchemaSpec.php',
'PhragmentSnapshot' => 'applications/phragment/storage/PhragmentSnapshot.php',
'PhragmentSnapshotChild' => 'applications/phragment/storage/PhragmentSnapshotChild.php',
'PhragmentSnapshotChildQuery' => 'applications/phragment/query/PhragmentSnapshotChildQuery.php',
'PhragmentSnapshotCreateController' => 'applications/phragment/controller/PhragmentSnapshotCreateController.php',
'PhragmentSnapshotDeleteController' => 'applications/phragment/controller/PhragmentSnapshotDeleteController.php',
'PhragmentSnapshotPHIDType' => 'applications/phragment/phid/PhragmentSnapshotPHIDType.php',
'PhragmentSnapshotPromoteController' => 'applications/phragment/controller/PhragmentSnapshotPromoteController.php',
'PhragmentSnapshotQuery' => 'applications/phragment/query/PhragmentSnapshotQuery.php',
'PhragmentSnapshotViewController' => 'applications/phragment/controller/PhragmentSnapshotViewController.php',
'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php',
'PhragmentVersionController' => 'applications/phragment/controller/PhragmentVersionController.php',
'PhragmentZIPController' => 'applications/phragment/controller/PhragmentZIPController.php',
'PhrequentConduitAPIMethod' => 'applications/phrequent/conduit/PhrequentConduitAPIMethod.php',
'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php',
'PhrequentCurtainExtension' => 'applications/phrequent/engineextension/PhrequentCurtainExtension.php',
@ -7710,7 +7676,6 @@ phutil_register_library_map(array(
'HarbormasterPlanRunController' => 'HarbormasterPlanController',
'HarbormasterPlanViewController' => 'HarbormasterPlanController',
'HarbormasterPrototypeBuildStepGroup' => 'HarbormasterBuildStepGroup',
'HarbormasterPublishFragmentBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
'HarbormasterQueryAutotargetsConduitAPIMethod' => 'HarbormasterConduitAPIMethod',
'HarbormasterQueryBuildablesConduitAPIMethod' => 'HarbormasterConduitAPIMethod',
'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod',
@ -10822,7 +10787,6 @@ phutil_register_library_map(array(
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow',
'PhabricatorPhortuneManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorPhortuneTestCase' => 'PhabricatorTestCase',
'PhabricatorPhragmentApplication' => 'PhabricatorApplication',
'PhabricatorPhrequentApplication' => 'PhabricatorApplication',
'PhabricatorPhrictionApplication' => 'PhabricatorApplication',
'PhabricatorPhurlApplication' => 'PhabricatorApplication',
@ -12442,50 +12406,6 @@ phutil_register_library_map(array(
'PhortuneSubscriptionTransactionType' => 'PhabricatorModularTransactionType',
'PhortuneSubscriptionWorker' => 'PhabricatorWorker',
'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider',
'PhragmentBrowseController' => 'PhragmentController',
'PhragmentCanCreateCapability' => 'PhabricatorPolicyCapability',
'PhragmentConduitAPIMethod' => 'ConduitAPIMethod',
'PhragmentController' => 'PhabricatorController',
'PhragmentCreateController' => 'PhragmentController',
'PhragmentDAO' => 'PhabricatorLiskDAO',
'PhragmentFragment' => array(
'PhragmentDAO',
'PhabricatorPolicyInterface',
),
'PhragmentFragmentPHIDType' => 'PhabricatorPHIDType',
'PhragmentFragmentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhragmentFragmentVersion' => array(
'PhragmentDAO',
'PhabricatorPolicyInterface',
),
'PhragmentFragmentVersionPHIDType' => 'PhabricatorPHIDType',
'PhragmentFragmentVersionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhragmentGetPatchConduitAPIMethod' => 'PhragmentConduitAPIMethod',
'PhragmentHistoryController' => 'PhragmentController',
'PhragmentPatchController' => 'PhragmentController',
'PhragmentPatchUtil' => 'Phobject',
'PhragmentPolicyController' => 'PhragmentController',
'PhragmentQueryFragmentsConduitAPIMethod' => 'PhragmentConduitAPIMethod',
'PhragmentRevertController' => 'PhragmentController',
'PhragmentSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'PhragmentSnapshot' => array(
'PhragmentDAO',
'PhabricatorPolicyInterface',
),
'PhragmentSnapshotChild' => array(
'PhragmentDAO',
'PhabricatorPolicyInterface',
),
'PhragmentSnapshotChildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhragmentSnapshotCreateController' => 'PhragmentController',
'PhragmentSnapshotDeleteController' => 'PhragmentController',
'PhragmentSnapshotPHIDType' => 'PhabricatorPHIDType',
'PhragmentSnapshotPromoteController' => 'PhragmentController',
'PhragmentSnapshotQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhragmentSnapshotViewController' => 'PhragmentController',
'PhragmentUpdateController' => 'PhragmentController',
'PhragmentVersionController' => 'PhragmentController',
'PhragmentZIPController' => 'PhragmentController',
'PhrequentConduitAPIMethod' => 'ConduitAPIMethod',
'PhrequentController' => 'PhabricatorController',
'PhrequentCurtainExtension' => 'PHUICurtainExtension',

View file

@ -1,89 +0,0 @@
<?php
final class HarbormasterPublishFragmentBuildStepImplementation
extends HarbormasterBuildStepImplementation {
public function getName() {
return pht('Publish Fragment');
}
public function getGenericDescription() {
return pht('Publish a fragment based on a file artifact.');
}
public function getBuildStepGroupKey() {
return HarbormasterPrototypeBuildStepGroup::GROUPKEY;
}
public function getDescription() {
return pht(
'Publish file artifact %s as fragment %s.',
$this->formatSettingForDescription('artifact'),
$this->formatSettingForDescription('path'));
}
public function execute(
HarbormasterBuild $build,
HarbormasterBuildTarget $build_target) {
$settings = $this->getSettings();
$variables = $build_target->getVariables();
$viewer = PhabricatorUser::getOmnipotentUser();
$path = $this->mergeVariables(
'vsprintf',
$settings['path'],
$variables);
$artifact = $build_target->loadArtifact($settings['artifact']);
$impl = $artifact->getArtifactImplementation();
$file = $impl->loadArtifactFile($viewer);
$fragment = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->withPaths(array($path))
->executeOne();
if ($fragment === null) {
PhragmentFragment::createFromFile(
$viewer,
$file,
$path,
PhabricatorPolicies::getMostOpenPolicy(),
PhabricatorPolicies::POLICY_USER);
} else {
if ($file->getMimeType() === 'application/zip') {
$fragment->updateFromZIP($viewer, $file);
} else {
$fragment->updateFromFile($viewer, $file);
}
}
}
public function getArtifactInputs() {
return array(
array(
'name' => pht('Publishes File'),
'key' => $this->getSetting('artifact'),
'type' => HarbormasterFileArtifact::ARTIFACTCONST,
),
);
}
public function getFieldSpecifications() {
return array(
'path' => array(
'name' => pht('Path'),
'type' => 'text',
'required' => true,
),
'artifact' => array(
'name' => pht('File Artifact'),
'type' => 'text',
'required' => true,
),
);
}
}

View file

@ -1,66 +0,0 @@
<?php
final class PhabricatorPhragmentApplication extends PhabricatorApplication {
public function getName() {
return pht('Phragment');
}
public function getBaseURI() {
return '/phragment/';
}
public function getShortDescription() {
return pht('Versioned Artifact Storage');
}
public function getIcon() {
return 'fa-floppy-o';
}
public function getTitleGlyph() {
return "\xE2\x96\x9B";
}
public function getApplicationGroup() {
return self::GROUP_UTILITIES;
}
public function isPrototype() {
return true;
}
public function getRoutes() {
return array(
'/phragment/' => array(
'' => 'PhragmentBrowseController',
'browse/(?P<dblob>.*)' => 'PhragmentBrowseController',
'create/(?P<dblob>.*)' => 'PhragmentCreateController',
'update/(?P<dblob>.+)' => 'PhragmentUpdateController',
'policy/(?P<dblob>.+)' => 'PhragmentPolicyController',
'history/(?P<dblob>.+)' => 'PhragmentHistoryController',
'zip/(?P<dblob>.+)' => 'PhragmentZIPController',
'zip@(?P<snapshot>[^/]+)/(?P<dblob>.+)' => 'PhragmentZIPController',
'version/(?P<id>[0-9]*)/' => 'PhragmentVersionController',
'patch/(?P<aid>[0-9x]*)/(?P<bid>[0-9]*)/' => 'PhragmentPatchController',
'revert/(?P<id>[0-9]*)/(?P<dblob>.*)' => 'PhragmentRevertController',
'snapshot/' => array(
'create/(?P<dblob>.*)' => 'PhragmentSnapshotCreateController',
'view/(?P<id>[0-9]*)/' => 'PhragmentSnapshotViewController',
'delete/(?P<id>[0-9]*)/' => 'PhragmentSnapshotDeleteController',
'promote/' => array(
'latest/(?P<dblob>.*)' => 'PhragmentSnapshotPromoteController',
'(?P<id>[0-9]*)/' => 'PhragmentSnapshotPromoteController',
),
),
),
);
}
protected function getCustomCapabilities() {
return array(
PhragmentCanCreateCapability::CAPABILITY => array(),
);
}
}

View file

@ -1,15 +0,0 @@
<?php
final class PhragmentCanCreateCapability extends PhabricatorPolicyCapability {
const CAPABILITY = 'phragment.create';
public function getCapabilityName() {
return pht('Can Create Fragments');
}
public function describeCapabilityRejection() {
return pht('You do not have permission to create fragments.');
}
}

View file

@ -1,10 +0,0 @@
<?php
abstract class PhragmentConduitAPIMethod extends ConduitAPIMethod {
final public function getApplication() {
return PhabricatorApplication::getByClass(
'PhabricatorPhragmentApplication');
}
}

View file

@ -1,192 +0,0 @@
<?php
final class PhragmentGetPatchConduitAPIMethod
extends PhragmentConduitAPIMethod {
public function getAPIMethodName() {
return 'phragment.getpatch';
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
public function getMethodDescription() {
return pht('Retrieve the patches to apply for a given set of files.');
}
protected function defineParamTypes() {
return array(
'path' => 'required string',
'state' => 'required dict<string, string>',
);
}
protected function defineReturnType() {
return 'nonempty dict';
}
protected function defineErrorTypes() {
return array(
'ERR_BAD_FRAGMENT' => pht('No such fragment exists.'),
);
}
protected function execute(ConduitAPIRequest $request) {
$path = $request->getValue('path');
$state = $request->getValue('state');
// The state is an array mapping file paths to hashes.
$patches = array();
// We need to get all of the mappings (like phragment.getstate) first
// so that we can detect deletions and creations of files.
$fragment = id(new PhragmentFragmentQuery())
->setViewer($request->getUser())
->withPaths(array($path))
->executeOne();
if ($fragment === null) {
throw new ConduitException('ERR_BAD_FRAGMENT');
}
$mappings = $fragment->getFragmentMappings(
$request->getUser(),
$fragment->getPath());
$file_phids = mpull(mpull($mappings, 'getLatestVersion'), 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setViewer($request->getUser())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
// Scan all of the files that the caller currently has and iterate
// over that.
foreach ($state as $path => $hash) {
// If $mappings[$path] exists, then the user has the file and it's
// also a fragment.
if (array_key_exists($path, $mappings)) {
$file_phid = $mappings[$path]->getLatestVersion()->getFilePHID();
if ($file_phid !== null) {
// If the file PHID is present, then we need to check the
// hashes to see if they are the same.
$hash_caller = strtolower($state[$path]);
$hash_current = $files[$file_phid]->getContentHash();
if ($hash_caller === $hash_current) {
// The user's version is identical to our version, so
// there is no update needed.
} else {
// The hash differs, and the user needs to update.
$patches[] = array(
'path' => $path,
'fileOld' => null,
'fileNew' => $files[$file_phid],
'hashOld' => $hash_caller,
'hashNew' => $hash_current,
'patchURI' => null,
);
}
} else {
// We have a record of this as a file, but there is no file
// attached to the latest version, so we consider this to be
// a deletion.
$patches[] = array(
'path' => $path,
'fileOld' => null,
'fileNew' => null,
'hashOld' => $hash_caller,
'hashNew' => PhragmentPatchUtil::EMPTY_HASH,
'patchURI' => null,
);
}
} else {
// If $mappings[$path] does not exist, then the user has a file,
// and we have absolutely no record of it what-so-ever (we haven't
// even recorded a deletion). Assuming most applications will store
// some form of data near their own files, this is probably a data
// file relevant for the application that is not versioned, so we
// don't tell the client to do anything with it.
}
}
// Check the remaining files that we know about but the caller has
// not reported.
foreach ($mappings as $path => $child) {
if (array_key_exists($path, $state)) {
// We have already evaluated this above.
} else {
$file_phid = $mappings[$path]->getLatestVersion()->getFilePHID();
if ($file_phid !== null) {
// If the file PHID is present, then this is a new file that
// we know about, but the caller does not. We need to tell
// the caller to create the file.
$hash_current = $files[$file_phid]->getContentHash();
$patches[] = array(
'path' => $path,
'fileOld' => null,
'fileNew' => $files[$file_phid],
'hashOld' => PhragmentPatchUtil::EMPTY_HASH,
'hashNew' => $hash_current,
'patchURI' => null,
);
} else {
// We have a record of deleting this file, and the caller hasn't
// reported it, so they've probably deleted it in a previous
// update.
}
}
}
// Before we can calculate patches, we need to resolve the old versions
// of files so we can draw diffs on them.
$hashes = array();
foreach ($patches as $patch) {
if ($patch['hashOld'] !== PhragmentPatchUtil::EMPTY_HASH) {
$hashes[] = $patch['hashOld'];
}
}
$old_files = array();
if (count($hashes) !== 0) {
$old_files = id(new PhabricatorFileQuery())
->setViewer($request->getUser())
->withContentHashes($hashes)
->execute();
}
$old_files = mpull($old_files, null, 'getContentHash');
foreach ($patches as $key => $patch) {
if ($patch['hashOld'] !== PhragmentPatchUtil::EMPTY_HASH) {
if (array_key_exists($patch['hashOld'], $old_files)) {
$patches[$key]['fileOld'] = $old_files[$patch['hashOld']];
} else {
// We either can't see or can't read the old file.
$patches[$key]['hashOld'] = PhragmentPatchUtil::EMPTY_HASH;
$patches[$key]['fileOld'] = null;
}
}
}
// Now run through all of the patch entries, calculate the patches
// and return the results.
foreach ($patches as $key => $patch) {
$data = PhragmentPatchUtil::calculatePatch(
$patches[$key]['fileOld'],
$patches[$key]['fileNew']);
unset($patches[$key]['fileOld']);
unset($patches[$key]['fileNew']);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$file = PhabricatorFile::newFromFileData(
$data,
array(
'name' => 'patch.dmp',
'ttl.relative' => phutil_units('24 hours in seconds'),
));
unset($unguarded);
$patches[$key]['patchURI'] = $file->getDownloadURI();
}
return $patches;
}
}

View file

@ -1,85 +0,0 @@
<?php
final class PhragmentQueryFragmentsConduitAPIMethod
extends PhragmentConduitAPIMethod {
public function getAPIMethodName() {
return 'phragment.queryfragments';
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
public function getMethodDescription() {
return pht('Query fragments based on their paths.');
}
protected function defineParamTypes() {
return array(
'paths' => 'required list<string>',
);
}
protected function defineReturnType() {
return 'nonempty dict';
}
protected function defineErrorTypes() {
return array(
'ERR_BAD_FRAGMENT' => pht('No such fragment exists.'),
);
}
protected function execute(ConduitAPIRequest $request) {
$paths = $request->getValue('paths');
$fragments = id(new PhragmentFragmentQuery())
->setViewer($request->getUser())
->withPaths($paths)
->execute();
$fragments = mpull($fragments, null, 'getPath');
foreach ($paths as $path) {
if (!array_key_exists($path, $fragments)) {
throw new ConduitException('ERR_BAD_FRAGMENT');
}
}
$results = array();
foreach ($fragments as $path => $fragment) {
$mappings = $fragment->getFragmentMappings(
$request->getUser(),
$fragment->getPath());
$file_phids = mpull(mpull($mappings, 'getLatestVersion'), 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setViewer($request->getUser())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
$result = array();
foreach ($mappings as $cpath => $child) {
$file_phid = $child->getLatestVersion()->getFilePHID();
if (!isset($files[$file_phid])) {
// Skip any files we don't have permission to access.
continue;
}
$file = $files[$file_phid];
$cpath = substr($child->getPath(), strlen($fragment->getPath()) + 1);
$result[] = array(
'phid' => $child->getPHID(),
'phidVersion' => $child->getLatestVersionPHID(),
'path' => $cpath,
'hash' => $file->getContentHash(),
'version' => $child->getLatestVersion()->getSequence(),
'uri' => $file->getViewURI(),
);
}
$results[$path] = $result;
}
return $results;
}
}

View file

@ -1,95 +0,0 @@
<?php
final class PhragmentBrowseController extends PhragmentController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$current = nonempty(last($parents), null);
$path = '';
if ($current !== null) {
$path = $current->getPath();
}
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
if ($this->hasApplicationCapability(
PhragmentCanCreateCapability::CAPABILITY)) {
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Fragment'))
->setHref($this->getApplicationURI('/create/'.$path))
->setIcon('fa-plus-square'));
}
$current_box = $this->createCurrentFragmentView($current, false);
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
$fragments = null;
if ($current === null) {
// Find all root fragments.
$fragments = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withDepths(array(1))
->execute();
} else {
// Find all child fragments.
$fragments = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withLeadingPath($current->getPath().'/')
->withDepths(array($current->getDepth() + 1))
->execute();
}
foreach ($fragments as $fragment) {
$item = id(new PHUIObjectItemView());
$item->setHeader($fragment->getName());
$item->setHref($fragment->getURI());
if (!$fragment->isDirectory()) {
$item->addAttribute(pht(
'Last Updated %s',
phabricator_datetime(
$fragment->getLatestVersion()->getDateCreated(),
$viewer)));
$item->addAttribute(pht(
'Latest Version %s',
$fragment->getLatestVersion()->getSequence()));
if ($fragment->isDeleted()) {
$item->setDisabled(true);
$item->addAttribute(pht('Deleted'));
}
} else {
$item->addAttribute(pht('Directory'));
}
$list->addItem($item);
}
$title = pht('Browse Fragments');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$current_box,
$list,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,232 +0,0 @@
<?php
abstract class PhragmentController extends PhabricatorController {
protected function loadParentFragments($path) {
$components = explode('/', $path);
$combinations = array();
$current = '';
foreach ($components as $component) {
$current .= '/'.$component;
$current = trim($current, '/');
if (trim($current) === '') {
continue;
}
$combinations[] = $current;
}
$fragments = array();
$results = id(new PhragmentFragmentQuery())
->setViewer($this->getRequest()->getUser())
->needLatestVersion(true)
->withPaths($combinations)
->execute();
foreach ($combinations as $combination) {
$found = false;
foreach ($results as $fragment) {
if ($fragment->getPath() === $combination) {
$fragments[] = $fragment;
$found = true;
break;
}
}
if (!$found) {
return null;
}
}
return $fragments;
}
protected function buildApplicationCrumbsWithPath(array $fragments) {
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb('/', '/phragment/');
foreach ($fragments as $parent) {
$crumbs->addTextCrumb(
$parent->getName(),
'/phragment/browse/'.$parent->getPath());
}
return $crumbs;
}
protected function createCurrentFragmentView($fragment, $is_history_view) {
if ($fragment === null) {
return null;
}
$viewer = $this->getRequest()->getUser();
$snapshot_phids = array();
$snapshots = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withPrimaryFragmentPHIDs(array($fragment->getPHID()))
->execute();
foreach ($snapshots as $snapshot) {
$snapshot_phids[] = $snapshot->getPHID();
}
$file = null;
$file_uri = null;
if (!$fragment->isDirectory()) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($fragment->getLatestVersion()->getFilePHID()))
->executeOne();
if ($file !== null) {
$file_uri = $file->getDownloadURI();
}
}
$header = id(new PHUIHeaderView())
->setHeader($fragment->getName())
->setPolicyObject($fragment)
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$fragment,
PhabricatorPolicyCapability::CAN_EDIT);
$zip_uri = $this->getApplicationURI('zip/'.$fragment->getPath());
$actions = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($fragment);
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Fragment'))
->setHref($this->isCorrectlyConfigured() ? $file_uri : null)
->setDisabled($file === null || !$this->isCorrectlyConfigured())
->setIcon('fa-download'));
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Contents as ZIP'))
->setHref($this->isCorrectlyConfigured() ? $zip_uri : null)
->setDisabled(!$this->isCorrectlyConfigured())
->setIcon('fa-floppy-o'));
if (!$fragment->isDirectory()) {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Update Fragment'))
->setHref($this->getApplicationURI('update/'.$fragment->getPath()))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)
->setIcon('fa-refresh'));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Convert to File'))
->setHref($this->getApplicationURI('update/'.$fragment->getPath()))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)
->setIcon('fa-file-o'));
}
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Set Fragment Policies'))
->setHref($this->getApplicationURI('policy/'.$fragment->getPath()))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)
->setIcon('fa-asterisk'));
if ($is_history_view) {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('View Child Fragments'))
->setHref($this->getApplicationURI('browse/'.$fragment->getPath()))
->setIcon('fa-search-plus'));
} else {
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('View History'))
->setHref($this->getApplicationURI('history/'.$fragment->getPath()))
->setIcon('fa-list'));
}
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Create Snapshot'))
->setHref($this->getApplicationURI(
'snapshot/create/'.$fragment->getPath()))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit)
->setIcon('fa-files-o'));
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Promote Snapshot to Here'))
->setHref($this->getApplicationURI(
'snapshot/promote/latest/'.$fragment->getPath()))
->setWorkflow(true)
->setDisabled(!$can_edit)
->setIcon('fa-arrow-circle-up'));
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($fragment)
->setActionList($actions);
if (!$fragment->isDirectory()) {
if ($fragment->isDeleted()) {
$properties->addProperty(
pht('Type'),
pht('File (Deleted)'));
} else {
$properties->addProperty(
pht('Type'),
pht('File'));
}
$properties->addProperty(
pht('Latest Version'),
$viewer->renderHandle($fragment->getLatestVersionPHID()));
} else {
$properties->addProperty(
pht('Type'),
pht('Directory'));
}
if (count($snapshot_phids) > 0) {
$properties->addProperty(
pht('Snapshots'),
$viewer->renderHandleList($snapshot_phids));
}
return id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
}
public function renderConfigurationWarningIfRequired() {
$alt = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
if ($alt === null) {
return id(new PHUIInfoView())
->setTitle(pht(
'%s must be configured!',
'security.alternate-file-domain'))
->setSeverity(PHUIInfoView::SEVERITY_ERROR)
->appendChild(
phutil_tag(
'p',
array(),
pht(
"Because Phragment generates files (such as ZIP archives and ".
"patches) as they are requested, it requires that you configure ".
"the `%s` option. This option on it's own will also provide ".
"additional security when serving files across Phabricator.",
'security.alternate-file-domain')));
}
return null;
}
/**
* We use this to disable the download links if the alternate domain is
* not configured correctly. Although the download links will mostly work
* for logged in users without an alternate domain, the behaviour is
* reasonably non-consistent and will deny public users, even if policies
* are configured otherwise (because the Files app does not support showing
* the info page to viewers who are not logged in).
*/
public function isCorrectlyConfigured() {
$alt = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
return $alt !== null;
}
}

View file

@ -1,135 +0,0 @@
<?php
final class PhragmentCreateController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parent = null;
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
if (count($parents) !== 0) {
$parent = idx($parents, count($parents) - 1, null);
}
$parent_path = '';
if ($parent !== null) {
$parent_path = $parent->getPath();
}
$parent_path = trim($parent_path, '/');
$fragment = id(new PhragmentFragment());
$error_view = null;
if ($request->isFormPost()) {
$errors = array();
$v_name = $request->getStr('name');
$v_fileid = $request->getInt('fileID');
$v_viewpolicy = $request->getStr('viewPolicy');
$v_editpolicy = $request->getStr('editPolicy');
if (strpos($v_name, '/') !== false) {
$errors[] = pht("The fragment name can not contain '/'.");
}
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withIDs(array($v_fileid))
->executeOne();
if (!$file) {
$errors[] = pht("The specified file doesn't exist.");
}
if (!count($errors)) {
$depth = 1;
if ($parent !== null) {
$depth = $parent->getDepth() + 1;
}
PhragmentFragment::createFromFile(
$viewer,
$file,
trim($parent_path.'/'.$v_name, '/'),
$v_viewpolicy,
$v_editpolicy);
return id(new AphrontRedirectResponse())
->setURI('/phragment/browse/'.trim($parent_path.'/'.$v_name, '/'));
} else {
$error_view = id(new PHUIInfoView())
->setErrors($errors)
->setTitle(pht('Errors while creating fragment'));
}
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($fragment)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Parent Path'))
->setDisabled(true)
->setValue('/'.trim($parent_path.'/', '/')))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('File ID'))
->setName('fileID'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setName('viewPolicy')
->setPolicyObject($fragment)
->setPolicies($policies)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setName('editPolicy')
->setPolicyObject($fragment)
->setPolicies($policies)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Create Fragment'))
->addCancelButton(
$this->getApplicationURI('browse/'.$parent_path)));
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('Create Fragment'));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Create Fragment'))
->setForm($form);
if ($error_view) {
$box->setInfoView($error_view);
}
$title = pht('Create Fragments');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,109 +0,0 @@
<?php
final class PhragmentHistoryController extends PhragmentController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$current = idx($parents, count($parents) - 1, null);
$path = $current->getPath();
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
if ($this->hasApplicationCapability(
PhragmentCanCreateCapability::CAPABILITY)) {
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Create Fragment'))
->setHref($this->getApplicationURI('/create/'.$path))
->setIcon('fa-plus-square'));
}
$current_box = $this->createCurrentFragmentView($current, true);
$versions = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($current->getPHID()))
->execute();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
$file_phids = mpull($versions, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$current,
PhabricatorPolicyCapability::CAN_EDIT);
$first = true;
foreach ($versions as $version) {
$item = id(new PHUIObjectItemView());
$item->setHeader(pht('Version %s', $version->getSequence()));
$item->setHref($version->getURI());
$item->addAttribute(phabricator_datetime(
$version->getDateCreated(),
$viewer));
if ($version->getFilePHID() === null) {
$item->setDisabled(true);
$item->addAttribute(pht('Deletion'));
}
if (!$first && $can_edit) {
$item->addAction(id(new PHUIListItemView())
->setIcon('fa-refresh')
->setRenderNameAsTooltip(true)
->setWorkflow(true)
->setName(pht('Revert to Here'))
->setHref($this->getApplicationURI(
'revert/'.$version->getID().'/'.$current->getPath())));
}
$disabled = !isset($files[$version->getFilePHID()]);
$action = id(new PHUIListItemView())
->setIcon('fa-download')
->setDisabled($disabled || !$this->isCorrectlyConfigured())
->setRenderNameAsTooltip(true)
->setName(pht('Download'));
if (!$disabled && $this->isCorrectlyConfigured()) {
$action->setHref($files[$version->getFilePHID()]
->getDownloadURI($version->getURI()));
}
$item->addAction($action);
$list->addItem($item);
$first = false;
}
$title = pht('Fragment History');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$current_box,
$list,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,97 +0,0 @@
<?php
final class PhragmentPatchController extends PhragmentController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$aid = $request->getURIData('aid');
$bid = $request->getURIData('bid');
// If "aid" is "x", then it means the user wants to generate
// a patch of an empty file to the version specified by "bid".
$ids = array($aid, $bid);
if ($aid === 'x') {
$ids = array($bid);
}
$versions = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withIDs($ids)
->execute();
$version_a = null;
if ($aid !== 'x') {
$version_a = idx($versions, $aid, null);
if ($version_a === null) {
return new Aphront404Response();
}
}
$version_b = idx($versions, $bid, null);
if ($version_b === null) {
return new Aphront404Response();
}
$file_phids = array();
if ($version_a !== null) {
$file_phids[] = $version_a->getFilePHID();
}
$file_phids[] = $version_b->getFilePHID();
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
$file_a = null;
if ($version_a != null) {
$file_a = idx($files, $version_a->getFilePHID(), null);
}
$file_b = idx($files, $version_b->getFilePHID(), null);
$patch = PhragmentPatchUtil::calculatePatch($file_a, $file_b);
if ($patch === null) {
// There are no differences between the two files, so we output
// an empty patch.
$patch = '';
}
$a_sequence = 'x';
if ($version_a !== null) {
$a_sequence = $version_a->getSequence();
}
$name =
$version_b->getFragment()->getName().'.'.
$a_sequence.'.'.
$version_b->getSequence().'.patch';
$return = $version_b->getURI();
if ($request->getExists('return')) {
$return = $request->getStr('return');
}
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$result = PhabricatorFile::newFromFileData(
$patch,
array(
'name' => $name,
'mime-type' => 'text/plain',
'ttl.relative' => phutil_units('24 hours in seconds'),
));
$result->attachToObject($version_b->getFragmentPHID());
unset($unguarded);
return id(new AphrontRedirectResponse())
->setURI($result->getDownloadURI($return));
}
}

View file

@ -1,106 +0,0 @@
<?php
final class PhragmentPolicyController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$fragment = idx($parents, count($parents) - 1, null);
$error_view = null;
if ($request->isFormPost()) {
$errors = array();
$v_view_policy = $request->getStr('viewPolicy');
$v_edit_policy = $request->getStr('editPolicy');
$v_replace_children = $request->getBool('replacePoliciesOnChildren');
$fragment->setViewPolicy($v_view_policy);
$fragment->setEditPolicy($v_edit_policy);
$fragment->save();
if ($v_replace_children) {
// If you can edit a fragment, you can forcibly set the policies
// on child fragments, regardless of whether you can see them or not.
$children = id(new PhragmentFragmentQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withLeadingPath($fragment->getPath().'/')
->execute();
$children_phids = mpull($children, 'getPHID');
$fragment->openTransaction();
foreach ($children as $child) {
$child->setViewPolicy($v_view_policy);
$child->setEditPolicy($v_edit_policy);
$child->save();
}
$fragment->saveTransaction();
}
return id(new AphrontRedirectResponse())
->setURI('/phragment/browse/'.$fragment->getPath());
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($fragment)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($fragment)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($fragment)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies))
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
'replacePoliciesOnChildren',
'true',
pht(
'Replace policies on child fragments with '.
'the policies above.')))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save Fragment Policies'))
->addCancelButton(
$this->getApplicationURI('browse/'.$fragment->getPath())));
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('Edit Fragment Policies'));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Edit Fragment Policies: %s', $fragment->getPath()))
->setValidationException(null)
->setForm($form);
$title = pht('Edit Fragment Policies');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,78 +0,0 @@
<?php
final class PhragmentRevertController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dblob = $request->getURIData('dblob');
$fragment = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->withPaths(array($dblob))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if ($fragment === null) {
return new Aphront404Response();
}
$version = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($fragment->getPHID()))
->withIDs(array($id))
->executeOne();
if ($version === null) {
return new Aphront404Response();
}
if ($request->isDialogFormPost()) {
$file_phid = $version->getFilePHID();
$file = null;
if ($file_phid !== null) {
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
if ($file === null) {
throw new Exception(
pht('The file associated with this version was not found.'));
}
}
if ($file === null) {
$fragment->deleteFile($viewer);
} else {
$fragment->updateFromFile($viewer, $file);
}
return id(new AphrontRedirectResponse())
->setURI($this->getApplicationURI('/history/'.$dblob));
}
return $this->createDialog($fragment, $version);
}
public function createDialog(
PhragmentFragment $fragment,
PhragmentFragmentVersion $version) {
$viewer = $this->getViewer();
$dialog = id(new AphrontDialogView())
->setTitle(pht('Really revert this fragment?'))
->setUser($this->getViewer())
->addSubmitButton(pht('Revert'))
->addCancelButton(pht('Cancel'))
->appendParagraph(pht(
'Reverting this fragment to version %d will create a new version of '.
'the fragment. It will not delete any version history.',
$version->getSequence()));
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}

View file

@ -1,170 +0,0 @@
<?php
final class PhragmentSnapshotCreateController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$fragment = nonempty(last($parents), null);
if ($fragment === null) {
return new Aphront404Response();
}
PhabricatorPolicyFilter::requireCapability(
$viewer,
$fragment,
PhabricatorPolicyCapability::CAN_EDIT);
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)
->withLeadingPath($fragment->getPath().'/')
->execute();
$errors = array();
if ($request->isFormPost()) {
$v_name = $request->getStr('name');
if (strlen($v_name) === 0) {
$errors[] = pht('You must specify a name.');
}
if (strpos($v_name, '/') !== false) {
$errors[] = pht('Snapshot names can not contain "/".');
}
if (!count($errors)) {
$snapshot = null;
try {
// Create the snapshot.
$snapshot = id(new PhragmentSnapshot())
->setPrimaryFragmentPHID($fragment->getPHID())
->setName($v_name)
->save();
} catch (AphrontDuplicateKeyQueryException $e) {
$errors[] = pht('A snapshot with this name already exists.');
}
if (!count($errors)) {
// Add the primary fragment.
id(new PhragmentSnapshotChild())
->setSnapshotPHID($snapshot->getPHID())
->setFragmentPHID($fragment->getPHID())
->setFragmentVersionPHID($fragment->getLatestVersionPHID())
->save();
// Add all of the child fragments.
foreach ($children as $child) {
id(new PhragmentSnapshotChild())
->setSnapshotPHID($snapshot->getPHID())
->setFragmentPHID($child->getPHID())
->setFragmentVersionPHID($child->getLatestVersionPHID())
->save();
}
return id(new AphrontRedirectResponse())
->setURI('/phragment/snapshot/view/'.$snapshot->getID());
}
}
}
$fragment_sequence = '-';
if ($fragment->getLatestVersion() !== null) {
$fragment_sequence = $fragment->getLatestVersion()->getSequence();
}
$rows = array();
$rows[] = phutil_tag(
'tr',
array(),
array(
phutil_tag('th', array(), pht('Fragment')),
phutil_tag('th', array(), pht('Version')),
));
$rows[] = phutil_tag(
'tr',
array(),
array(
phutil_tag('td', array(), $fragment->getPath()),
phutil_tag('td', array(), $fragment_sequence),
));
foreach ($children as $child) {
$sequence = '-';
if ($child->getLatestVersion() !== null) {
$sequence = $child->getLatestVersion()->getSequence();
}
$rows[] = phutil_tag(
'tr',
array(),
array(
phutil_tag('td', array(), $child->getPath()),
phutil_tag('td', array(), $sequence),
));
}
$table = phutil_tag(
'table',
array('class' => 'remarkup-table'),
$rows);
$container = phutil_tag(
'div',
array('class' => 'phabricator-remarkup'),
array(
phutil_tag(
'p',
array(),
pht(
'The snapshot will contain the following fragments at '.
'the specified versions: ')),
$table,
));
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Fragment Path'))
->setDisabled(true)
->setValue('/'.$fragment->getPath()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Snapshot Name'))
->setName('name'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Create Snapshot'))
->addCancelButton(
$this->getApplicationURI('browse/'.$fragment->getPath())))
->appendChild(
id(new PHUIFormDividerControl()))
->appendInstructions($container);
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('Create Snapshot'));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Create Snapshot of %s', $fragment->getName()))
->setFormErrors($errors)
->setForm($form);
$title = pht('Create Snapshot');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,47 +0,0 @@
<?php
final class PhragmentSnapshotDeleteController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$snapshot = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->requireCapabilities(array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($id))
->executeOne();
if ($snapshot === null) {
return new Aphront404Response();
}
if ($request->isDialogFormPost()) {
$fragment_uri = $snapshot->getPrimaryFragment()->getURI();
$snapshot->delete();
return id(new AphrontRedirectResponse())
->setURI($fragment_uri);
}
return $this->createDialog();
}
public function createDialog() {
$viewer = $this->getViewer();
$dialog = id(new AphrontDialogView())
->setTitle(pht('Really delete this snapshot?'))
->setUser($this->getViewer())
->addSubmitButton(pht('Delete'))
->addCancelButton(pht('Cancel'))
->appendParagraph(pht(
'Deleting this snapshot is a permanent operation. You can not '.
'recover the state of the snapshot.'));
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}

View file

@ -1,188 +0,0 @@
<?php
final class PhragmentSnapshotPromoteController extends PhragmentController {
private $targetSnapshot;
private $targetFragment;
private $snapshots;
private $options;
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$dblob = $request->getURIData('dblob');
// When the user is promoting a snapshot to the latest version, the
// identifier is a fragment path.
if ($dblob !== null) {
$this->targetFragment = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->requireCapabilities(array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withPaths(array($dblob))
->executeOne();
if ($this->targetFragment === null) {
return new Aphront404Response();
}
$this->snapshots = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withPrimaryFragmentPHIDs(array($this->targetFragment->getPHID()))
->execute();
}
// When the user is promoting a snapshot to another snapshot, the
// identifier is another snapshot ID.
if ($id !== null) {
$this->targetSnapshot = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->requireCapabilities(array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($id))
->executeOne();
if ($this->targetSnapshot === null) {
return new Aphront404Response();
}
$this->snapshots = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withPrimaryFragmentPHIDs(array(
$this->targetSnapshot->getPrimaryFragmentPHID(),
))
->execute();
}
// If there's no identifier, just 404.
if ($this->snapshots === null) {
return new Aphront404Response();
}
// Work out what options the user has.
$this->options = mpull(
$this->snapshots,
'getName',
'getID');
if ($id !== null) {
unset($this->options[$id]);
}
// If there's no options, show a dialog telling the
// user there are no snapshots to promote.
if (count($this->options) === 0) {
return id(new AphrontDialogResponse())->setDialog(
id(new AphrontDialogView())
->setTitle(pht('No snapshots to promote'))
->appendParagraph(pht(
'There are no snapshots available to promote.'))
->setUser($this->getViewer())
->addCancelButton(pht('Cancel')));
}
// Handle snapshot promotion.
if ($request->isDialogFormPost()) {
$snapshot = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withIDs(array($request->getStr('snapshot')))
->executeOne();
if ($snapshot === null) {
return new Aphront404Response();
}
$snapshot->openTransaction();
// Delete all existing child entries.
$children = id(new PhragmentSnapshotChildQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withSnapshotPHIDs(array($snapshot->getPHID()))
->execute();
foreach ($children as $child) {
$child->delete();
}
if ($id === null) {
// The user is promoting the snapshot to the latest version.
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)
->withLeadingPath($this->targetFragment->getPath().'/')
->execute();
// Add the primary fragment.
id(new PhragmentSnapshotChild())
->setSnapshotPHID($snapshot->getPHID())
->setFragmentPHID($this->targetFragment->getPHID())
->setFragmentVersionPHID(
$this->targetFragment->getLatestVersionPHID())
->save();
// Add all of the child fragments.
foreach ($children as $child) {
id(new PhragmentSnapshotChild())
->setSnapshotPHID($snapshot->getPHID())
->setFragmentPHID($child->getPHID())
->setFragmentVersionPHID($child->getLatestVersionPHID())
->save();
}
} else {
// The user is promoting the snapshot to another snapshot. We just
// copy the other snapshot's child entries and change the snapshot
// PHID to make it identical.
$children = id(new PhragmentSnapshotChildQuery())
->setViewer($viewer)
->withSnapshotPHIDs(array($this->targetSnapshot->getPHID()))
->execute();
foreach ($children as $child) {
id(new PhragmentSnapshotChild())
->setSnapshotPHID($snapshot->getPHID())
->setFragmentPHID($child->getFragmentPHID())
->setFragmentVersionPHID($child->getFragmentVersionPHID())
->save();
}
}
$snapshot->saveTransaction();
if ($id === null) {
return id(new AphrontRedirectResponse())
->setURI($this->targetFragment->getURI());
} else {
return id(new AphrontRedirectResponse())
->setURI($this->targetSnapshot->getURI());
}
}
return $this->createDialog($id);
}
public function createDialog($id) {
$viewer = $this->getViewer();
$dialog = id(new AphrontDialogView())
->setTitle(pht('Promote which snapshot?'))
->setUser($this->getViewer())
->addSubmitButton(pht('Promote'))
->addCancelButton(pht('Cancel'));
if ($id === null) {
// The user is promoting a snapshot to the latest version.
$dialog->appendParagraph(pht(
'Select the snapshot you want to promote to the latest version:'));
} else {
// The user is promoting a snapshot to another snapshot.
$dialog->appendParagraph(pht(
"Select the snapshot you want to promote to '%s':",
$this->targetSnapshot->getName()));
}
$dialog->appendChild(
id(new AphrontFormSelectControl())
->setUser($viewer)
->setName('snapshot')
->setOptions($this->options));
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}

View file

@ -1,145 +0,0 @@
<?php
final class PhragmentSnapshotViewController extends PhragmentController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$snapshot = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if ($snapshot === null) {
return new Aphront404Response();
}
$box = $this->createSnapshotView($snapshot);
$fragment = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->withPHIDs(array($snapshot->getPrimaryFragmentPHID()))
->executeOne();
if ($fragment === null) {
return new Aphront404Response();
}
$parents = $this->loadParentFragments($fragment->getPath());
if ($parents === null) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('"%s" Snapshot', $snapshot->getName()));
$children = id(new PhragmentSnapshotChildQuery())
->setViewer($viewer)
->needFragments(true)
->needFragmentVersions(true)
->withSnapshotPHIDs(array($snapshot->getPHID()))
->execute();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($children as $child) {
$item = id(new PHUIObjectItemView())
->setHeader($child->getFragment()->getPath());
if ($child->getFragmentVersion() !== null) {
$item
->setHref($child->getFragmentVersion()->getURI())
->addAttribute(pht(
'Version %s',
$child->getFragmentVersion()->getSequence()));
} else {
$item
->setHref($child->getFragment()->getURI())
->addAttribute(pht('Directory'));
}
$list->addItem($item);
}
$title = pht('View Snapshot');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
$list,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
protected function createSnapshotView($snapshot) {
if ($snapshot === null) {
return null;
}
$viewer = $this->getRequest()->getUser();
$header = id(new PHUIHeaderView())
->setHeader(pht('"%s" Snapshot', $snapshot->getName()))
->setPolicyObject($snapshot)
->setUser($viewer);
$zip_uri = $this->getApplicationURI(
'zip@'.$snapshot->getName().
'/'.$snapshot->getPrimaryFragment()->getPath());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$snapshot,
PhabricatorPolicyCapability::CAN_EDIT);
$actions = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($snapshot);
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Snapshot as ZIP'))
->setHref($this->isCorrectlyConfigured() ? $zip_uri : null)
->setDisabled(!$this->isCorrectlyConfigured())
->setIcon('fa-floppy-o'));
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Delete Snapshot'))
->setHref($this->getApplicationURI(
'snapshot/delete/'.$snapshot->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(true)
->setIcon('fa-times'));
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Promote Another Snapshot to Here'))
->setHref($this->getApplicationURI(
'snapshot/promote/'.$snapshot->getID().'/'))
->setDisabled(!$can_edit)
->setWorkflow(true)
->setIcon('fa-arrow-up'));
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($snapshot)
->setActionList($actions);
$properties->addProperty(
pht('Name'),
$snapshot->getName());
$properties->addProperty(
pht('Fragment'),
$viewer->renderHandle($snapshot->getPrimaryFragmentPHID()));
return id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
}
}

View file

@ -1,80 +0,0 @@
<?php
final class PhragmentUpdateController extends PhragmentController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$fragment = idx($parents, count($parents) - 1, null);
$error_view = null;
if ($request->isFormPost()) {
$errors = array();
$v_fileid = $request->getInt('fileID');
$file = id(new PhabricatorFile())->load($v_fileid);
if ($file === null) {
$errors[] = pht('The specified file doesn\'t exist.');
}
if (!count($errors)) {
// If the file is a ZIP archive (has application/zip mimetype)
// then we extract the zip and apply versions for each of the
// individual fragments, creating and deleting files as needed.
if ($file->getMimeType() === 'application/zip') {
$fragment->updateFromZIP($viewer, $file);
} else {
$fragment->updateFromFile($viewer, $file);
}
return id(new AphrontRedirectResponse())
->setURI('/phragment/browse/'.$fragment->getPath());
} else {
$error_view = id(new PHUIInfoView())
->setErrors($errors)
->setTitle(pht('Errors while updating fragment'));
}
}
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('File ID'))
->setName('fileID'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Update Fragment'))
->addCancelButton(
$this->getApplicationURI('browse/'.$fragment->getPath())));
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('Update Fragment'));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Update Fragment: %s', $fragment->getPath()))
->setValidationException(null)
->setForm($form);
$title = pht('Update Fragment');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -1,125 +0,0 @@
<?php
final class PhragmentVersionController extends PhragmentController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$id = $request->getURIData('id');
$version = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if ($version === null) {
return new Aphront404Response();
}
$parents = $this->loadParentFragments($version->getFragment()->getPath());
if ($parents === null) {
return new Aphront404Response();
}
$current = idx($parents, count($parents) - 1, null);
$crumbs = $this->buildApplicationCrumbsWithPath($parents);
$crumbs->addTextCrumb(pht('View Version %d', $version->getSequence()));
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($version->getFilePHID()))
->executeOne();
if ($file !== null) {
$file_uri = $file->getDownloadURI();
}
$header = id(new PHUIHeaderView())
->setHeader(pht(
'%s at version %d',
$version->getFragment()->getName(),
$version->getSequence()))
->setPolicyObject($version)
->setUser($viewer);
$actions = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($version);
$actions->addAction(
id(new PhabricatorActionView())
->setName(pht('Download Version'))
->setDisabled($file === null || !$this->isCorrectlyConfigured())
->setHref($this->isCorrectlyConfigured() ? $file_uri : null)
->setIcon('fa-download'));
$properties = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($version)
->setActionList($actions);
$properties->addProperty(
pht('File'),
$viewer->renderHandle($version->getFilePHID()));
$box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
$title = pht('View Version');
$view = array(
$this->renderConfigurationWarningIfRequired(),
$box,
$this->renderPreviousVersionList($version),
);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function renderPreviousVersionList(
PhragmentFragmentVersion $version) {
$viewer = $this->getViewer();
$previous_versions = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($version->getFragmentPHID()))
->withSequenceBefore($version->getSequence())
->execute();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($previous_versions as $previous_version) {
$item = id(new PHUIObjectItemView());
$item->setHeader(pht('Version %s', $previous_version->getSequence()));
$item->setHref($previous_version->getURI());
$item->addAttribute(phabricator_datetime(
$previous_version->getDateCreated(),
$viewer));
$patch_uri = $this->getApplicationURI(
'patch/'.$previous_version->getID().'/'.$version->getID());
$item->addAction(id(new PHUIListItemView())
->setIcon('fa-file-o')
->setName(pht('Get Patch'))
->setHref($this->isCorrectlyConfigured() ? $patch_uri : null)
->setDisabled(!$this->isCorrectlyConfigured()));
$list->addItem($item);
}
$item = id(new PHUIObjectItemView());
$item->setHeader(pht('Prior to Version 0'));
$item->addAttribute(pht('Prior to any content (empty file)'));
$item->addAction(id(new PHUIListItemView())
->setIcon('fa-file-o')
->setName(pht('Get Patch'))
->setHref($this->getApplicationURI(
'patch/x/'.$version->getID())));
$list->addItem($item);
return $list;
}
}

View file

@ -1,154 +0,0 @@
<?php
final class PhragmentZIPController extends PhragmentController {
private $snapshotCache;
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$dblob = $request->getURIData('dblob');
$snapshot = $request->getURIData('snapshot');
$parents = $this->loadParentFragments($dblob);
if ($parents === null) {
return new Aphront404Response();
}
$fragment = idx($parents, count($parents) - 1, null);
if ($snapshot !== null) {
$snapshot = id(new PhragmentSnapshotQuery())
->setViewer($viewer)
->withPrimaryFragmentPHIDs(array($fragment->getPHID()))
->withNames(array($snapshot))
->executeOne();
if ($snapshot === null) {
return new Aphront404Response();
}
$cache = id(new PhragmentSnapshotChildQuery())
->setViewer($viewer)
->needFragmentVersions(true)
->withSnapshotPHIDs(array($snapshot->getPHID()))
->execute();
$this->snapshotCache = mpull(
$cache,
'getFragmentVersion',
'getFragmentPHID');
}
$temp = new TempFile();
$zip = null;
try {
$zip = new ZipArchive();
} catch (Exception $e) {
$dialog = new AphrontDialogView();
$dialog->setUser($viewer);
$inst = pht(
'This system does not have the ZIP PHP extension installed. This '.
'is required to download ZIPs from Phragment.');
$dialog->setTitle(pht('ZIP Extension Not Installed'));
$dialog->appendParagraph($inst);
$dialog->addCancelButton('/phragment/browse/'.$dblob);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
if (!$zip->open((string)$temp, ZipArchive::CREATE)) {
throw new Exception(pht('Unable to create ZIP archive!'));
}
$mappings = $this->getFragmentMappings(
$fragment, $fragment->getPath(), $snapshot);
$phids = array();
foreach ($mappings as $path => $file_phid) {
$phids[] = $file_phid;
}
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs($phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($mappings as $path => $file_phid) {
if (!isset($files[$file_phid])) {
// The path is most likely pointing to a deleted fragment, which
// hence no longer has a file associated with it.
unset($mappings[$path]);
continue;
}
$mappings[$path] = $files[$file_phid];
}
foreach ($mappings as $path => $file) {
if ($file !== null) {
$zip->addFromString($path, $file->loadFileData());
}
}
$zip->close();
$zip_name = $fragment->getName();
if (substr($zip_name, -4) !== '.zip') {
$zip_name .= '.zip';
}
$data = Filesystem::readFile((string)$temp);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$file = PhabricatorFile::newFromFileData(
$data,
array(
'name' => $zip_name,
'ttl.relative' => phutil_units('24 hours in seconds'),
));
$file->attachToObject($fragment->getPHID());
unset($unguarded);
$return = $fragment->getURI();
if ($request->getExists('return')) {
$return = $request->getStr('return');
}
return id(new AphrontRedirectResponse())
->setIsExternal(true)
->setURI($file->getDownloadURI($return));
}
/**
* Returns a list of mappings like array('some/path.txt' => 'file PHID');
*/
private function getFragmentMappings(
PhragmentFragment $current,
$base_path,
$snapshot) {
$mappings = $current->getFragmentMappings(
$this->getRequest()->getUser(),
$base_path);
$result = array();
foreach ($mappings as $path => $fragment) {
$version = $this->getVersion($fragment, $snapshot);
if ($version !== null) {
$result[$path] = $version->getFilePHID();
}
}
return $result;
}
private function getVersion($fragment, $snapshot) {
if ($snapshot === null) {
return $fragment->getLatestVersion();
} else {
return idx($this->snapshotCache, $fragment->getPHID(), null);
}
}
}

View file

@ -1,44 +0,0 @@
<?php
final class PhragmentFragmentPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PHRF';
public function getTypeName() {
return pht('Fragment');
}
public function newObject() {
return new PhragmentFragment();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhragmentFragmentQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$fragment = $objects[$phid];
$handle->setName(pht(
'Fragment %s: %s',
$fragment->getID(),
$fragment->getName()));
$handle->setURI($fragment->getURI());
}
}
}

View file

@ -1,44 +0,0 @@
<?php
final class PhragmentFragmentVersionPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PHRV';
public function getTypeName() {
return pht('Fragment Version');
}
public function newObject() {
return new PhragmentFragmentVersion();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhragmentFragmentVersionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$version = $objects[$phid];
$handle->setName(pht(
'Fragment Version %d: %s',
$version->getSequence(),
$version->getFragment()->getName()));
$handle->setURI($version->getURI());
}
}
}

View file

@ -1,43 +0,0 @@
<?php
final class PhragmentSnapshotPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PHRS';
public function getTypeName() {
return pht('Snapshot');
}
public function newObject() {
return new PhragmentSnapshot();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhragmentSnapshotQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$snapshot = $objects[$phid];
$handle->setName(pht(
'Snapshot: %s',
$snapshot->getName()));
$handle->setURI($snapshot->getURI());
}
}
}

View file

@ -1,130 +0,0 @@
<?php
final class PhragmentFragmentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $paths;
private $leadingPath;
private $depths;
private $needLatestVersion;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withPaths(array $paths) {
$this->paths = $paths;
return $this;
}
public function withLeadingPath($path) {
$this->leadingPath = $path;
return $this;
}
public function withDepths($depths) {
$this->depths = $depths;
return $this;
}
public function needLatestVersion($need_latest_version) {
$this->needLatestVersion = $need_latest_version;
return $this;
}
protected function loadPage() {
$table = new PhragmentFragment();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->paths) {
$where[] = qsprintf(
$conn,
'path IN (%Ls)',
$this->paths);
}
if ($this->leadingPath) {
$where[] = qsprintf(
$conn,
'path LIKE %>',
$this->leadingPath);
}
if ($this->depths) {
$where[] = qsprintf(
$conn,
'depth IN (%Ld)',
$this->depths);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
protected function didFilterPage(array $page) {
if ($this->needLatestVersion) {
$versions = array();
$version_phids = array_filter(mpull($page, 'getLatestVersionPHID'));
if ($version_phids) {
$versions = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($version_phids)
->setParentQuery($this)
->execute();
$versions = mpull($versions, null, 'getPHID');
}
foreach ($page as $key => $fragment) {
$version_phid = $fragment->getLatestVersionPHID();
if (empty($versions[$version_phid])) {
continue;
}
$fragment->attachLatestVersion($versions[$version_phid]);
}
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}

View file

@ -1,123 +0,0 @@
<?php
final class PhragmentFragmentVersionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $fragmentPHIDs;
private $sequences;
private $sequenceBefore;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withFragmentPHIDs(array $fragment_phids) {
$this->fragmentPHIDs = $fragment_phids;
return $this;
}
public function withSequences(array $sequences) {
$this->sequences = $sequences;
return $this;
}
public function withSequenceBefore($current) {
$this->sequenceBefore = $current;
return $this;
}
protected function loadPage() {
$table = new PhragmentFragmentVersion();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->fragmentPHIDs) {
$where[] = qsprintf(
$conn,
'fragmentPHID IN (%Ls)',
$this->fragmentPHIDs);
}
if ($this->sequences) {
$where[] = qsprintf(
$conn,
'sequence IN (%Ld)',
$this->sequences);
}
if ($this->sequenceBefore !== null) {
$where[] = qsprintf(
$conn,
'sequence < %d',
$this->sequenceBefore);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
protected function willFilterPage(array $page) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $version) {
$fragment_phid = $version->getFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$version->attachFragment($fragments[$fragment_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}

View file

@ -1,174 +0,0 @@
<?php
final class PhragmentSnapshotChildQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $snapshotPHIDs;
private $fragmentPHIDs;
private $fragmentVersionPHIDs;
private $needFragments;
private $needFragmentVersions;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withSnapshotPHIDs(array $snapshot_phids) {
$this->snapshotPHIDs = $snapshot_phids;
return $this;
}
public function withFragmentPHIDs(array $fragment_phids) {
$this->fragmentPHIDs = $fragment_phids;
return $this;
}
public function withFragmentVersionPHIDs(array $fragment_version_phids) {
$this->fragmentVersionPHIDs = $fragment_version_phids;
return $this;
}
public function needFragments($need_fragments) {
$this->needFragments = $need_fragments;
return $this;
}
public function needFragmentVersions($need_fragment_versions) {
$this->needFragmentVersions = $need_fragment_versions;
return $this;
}
protected function loadPage() {
$table = new PhragmentSnapshotChild();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->snapshotPHIDs) {
$where[] = qsprintf(
$conn,
'snapshotPHID IN (%Ls)',
$this->snapshotPHIDs);
}
if ($this->fragmentPHIDs) {
$where[] = qsprintf(
$conn,
'fragmentPHID IN (%Ls)',
$this->fragmentPHIDs);
}
if ($this->fragmentVersionPHIDs) {
$where[] = qsprintf(
$conn,
'fragmentVersionPHID IN (%Ls)',
$this->fragmentVersionPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
protected function willFilterPage(array $page) {
$snapshots = array();
$snapshot_phids = array_filter(mpull($page, 'getSnapshotPHID'));
if ($snapshot_phids) {
$snapshots = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($snapshot_phids)
->setParentQuery($this)
->execute();
$snapshots = mpull($snapshots, null, 'getPHID');
}
foreach ($page as $key => $child) {
$snapshot_phid = $child->getSnapshotPHID();
if (empty($snapshots[$snapshot_phid])) {
unset($page[$key]);
continue;
}
$child->attachSnapshot($snapshots[$snapshot_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
if ($this->needFragments) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $child) {
$fragment_phid = $child->getFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$child->attachFragment($fragments[$fragment_phid]);
}
}
if ($this->needFragmentVersions) {
$fragment_versions = array();
$fragment_version_phids = array_filter(mpull(
$page,
'getFragmentVersionPHID'));
if ($fragment_version_phids) {
$fragment_versions = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_version_phids)
->setParentQuery($this)
->execute();
$fragment_versions = mpull($fragment_versions, null, 'getPHID');
}
foreach ($page as $key => $child) {
$fragment_version_phid = $child->getFragmentVersionPHID();
if (empty($fragment_versions[$fragment_version_phid])) {
continue;
}
$child->attachFragmentVersion(
$fragment_versions[$fragment_version_phid]);
}
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}

View file

@ -1,111 +0,0 @@
<?php
final class PhragmentSnapshotQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $primaryFragmentPHIDs;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withPrimaryFragmentPHIDs(array $primary_fragment_phids) {
$this->primaryFragmentPHIDs = $primary_fragment_phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
protected function loadPage() {
$table = new PhragmentSnapshot();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->primaryFragmentPHIDs !== null) {
$where[] = qsprintf(
$conn,
'primaryFragmentPHID IN (%Ls)',
$this->primaryFragmentPHIDs);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'name IN (%Ls)',
$this->names);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
protected function willFilterPage(array $page) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getPrimaryFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $snapshot) {
$fragment_phid = $snapshot->getPrimaryFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$snapshot->attachPrimaryFragment($fragments[$fragment_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}

View file

@ -1,9 +0,0 @@
<?php
abstract class PhragmentDAO extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'phragment';
}
}

View file

@ -1,349 +0,0 @@
<?php
final class PhragmentFragment extends PhragmentDAO
implements PhabricatorPolicyInterface {
protected $path;
protected $depth;
protected $latestVersionPHID;
protected $viewPolicy;
protected $editPolicy;
private $latestVersion = self::ATTACHABLE;
private $file = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'path' => 'text128',
'depth' => 'uint32',
'latestVersionPHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_path' => array(
'columns' => array('path'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhragmentFragmentPHIDType::TYPECONST);
}
public function getURI() {
return '/phragment/browse/'.$this->getPath();
}
public function getName() {
return basename($this->path);
}
public function getFile() {
return $this->assertAttached($this->file);
}
public function attachFile(PhabricatorFile $file) {
return $this->file = $file;
}
public function isDirectory() {
return $this->latestVersionPHID === null;
}
public function isDeleted() {
return $this->getLatestVersion()->getFilePHID() === null;
}
public function getLatestVersion() {
if ($this->latestVersionPHID === null) {
return null;
}
return $this->assertAttached($this->latestVersion);
}
public function attachLatestVersion(PhragmentFragmentVersion $version) {
return $this->latestVersion = $version;
}
/* -( Updating ) --------------------------------------------------------- */
/**
* Create a new fragment from a file.
*/
public static function createFromFile(
PhabricatorUser $viewer,
PhabricatorFile $file = null,
$path = null,
$view_policy = null,
$edit_policy = null) {
$fragment = id(new PhragmentFragment());
$fragment->setPath($path);
$fragment->setDepth(count(explode('/', $path)));
$fragment->setLatestVersionPHID(null);
$fragment->setViewPolicy($view_policy);
$fragment->setEditPolicy($edit_policy);
$fragment->save();
// Directory fragments have no versions associated with them, so we
// just return the fragment at this point.
if ($file === null) {
return $fragment;
}
if ($file->getMimeType() === 'application/zip') {
$fragment->updateFromZIP($viewer, $file);
} else {
$fragment->updateFromFile($viewer, $file);
}
return $fragment;
}
/**
* Set the specified file as the next version for the fragment.
*/
public function updateFromFile(
PhabricatorUser $viewer,
PhabricatorFile $file) {
$existing = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($this->getPHID()))
->execute();
$sequence = count($existing);
$this->openTransaction();
$version = id(new PhragmentFragmentVersion());
$version->setSequence($sequence);
$version->setFragmentPHID($this->getPHID());
$version->setFilePHID($file->getPHID());
$version->save();
$this->setLatestVersionPHID($version->getPHID());
$this->save();
$this->saveTransaction();
$file->attachToObject($version->getPHID());
}
/**
* Apply the specified ZIP archive onto the fragment, removing
* and creating fragments as needed.
*/
public function updateFromZIP(
PhabricatorUser $viewer,
PhabricatorFile $file) {
if ($file->getMimeType() !== 'application/zip') {
throw new Exception(
pht("File must have mimetype '%s'.", 'application/zip'));
}
// First apply the ZIP as normal.
$this->updateFromFile($viewer, $file);
// Ensure we have ZIP support.
$zip = null;
try {
$zip = new ZipArchive();
} catch (Exception $e) {
// The server doesn't have php5-zip, so we can't do recursive updates.
return;
}
$temp = new TempFile();
Filesystem::writeFile($temp, $file->loadFileData());
if (!$zip->open($temp)) {
throw new Exception(pht('Unable to open ZIP.'));
}
// Get all of the paths and their data from the ZIP.
$mappings = array();
for ($i = 0; $i < $zip->numFiles; $i++) {
$path = trim($zip->getNameIndex($i), '/');
$stream = $zip->getStream($path);
$data = null;
// If the stream is false, then it is a directory entry. We leave
// $data set to null for directories so we know not to create a
// version entry for them.
if ($stream !== false) {
$data = stream_get_contents($stream);
fclose($stream);
}
$mappings[$path] = $data;
}
// We need to detect any directories that are in the ZIP folder that
// aren't explicitly noted in the ZIP. This can happen if the file
// entries in the ZIP look like:
//
// * something/blah.png
// * something/other.png
// * test.png
//
// Where there is no explicit "something/" entry.
foreach ($mappings as $path_key => $data) {
if ($data === null) {
continue;
}
$directory = dirname($path_key);
while ($directory !== '.') {
if (!array_key_exists($directory, $mappings)) {
$mappings[$directory] = null;
}
if (dirname($directory) === $directory) {
// dirname() will not reduce this directory any further; to
// prevent infinite loop we just break out here.
break;
}
$directory = dirname($directory);
}
}
// Adjust the paths relative to this fragment so we can look existing
// fragments up in the DB.
$base_path = $this->getPath();
$paths = array();
foreach ($mappings as $p => $data) {
$paths[] = $base_path.'/'.$p;
}
// FIXME: What happens when a child exists, but the current user
// can't see it. We're going to create a new child with the exact
// same path and then bad things will happen.
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)
->withLeadingPath($this->getPath().'/')
->execute();
$children = mpull($children, null, 'getPath');
// Iterate over the existing fragments.
foreach ($children as $full_path => $child) {
$path = substr($full_path, strlen($base_path) + 1);
if (array_key_exists($path, $mappings)) {
if ($child->isDirectory() && $mappings[$path] === null) {
// Don't create a version entry for a directory
// (unless it's been converted into a file).
continue;
}
// The file is being updated.
$file = PhabricatorFile::newFromFileData(
$mappings[$path],
array('name' => basename($path)));
$child->updateFromFile($viewer, $file);
} else {
// The file is being deleted.
$child->deleteFile($viewer);
}
}
// Iterate over the mappings to find new files.
foreach ($mappings as $path => $data) {
if (!array_key_exists($base_path.'/'.$path, $children)) {
// The file is being created. If the data is null,
// then this is explicitly a directory being created.
$file = null;
if ($mappings[$path] !== null) {
$file = PhabricatorFile::newFromFileData(
$mappings[$path],
array('name' => basename($path)));
}
self::createFromFile(
$viewer,
$file,
$base_path.'/'.$path,
$this->getViewPolicy(),
$this->getEditPolicy());
}
}
}
/**
* Delete the contents of the specified fragment.
*/
public function deleteFile(PhabricatorUser $viewer) {
$existing = id(new PhragmentFragmentVersionQuery())
->setViewer($viewer)
->withFragmentPHIDs(array($this->getPHID()))
->execute();
$sequence = count($existing);
$this->openTransaction();
$version = id(new PhragmentFragmentVersion());
$version->setSequence($sequence);
$version->setFragmentPHID($this->getPHID());
$version->setFilePHID(null);
$version->save();
$this->setLatestVersionPHID($version->getPHID());
$this->save();
$this->saveTransaction();
}
/* -( Utility ) ---------------------------------------------------------- */
public function getFragmentMappings(
PhabricatorUser $viewer,
$base_path) {
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)
->withLeadingPath($this->getPath().'/')
->withDepths(array($this->getDepth() + 1))
->execute();
if (count($children) === 0) {
$path = substr($this->getPath(), strlen($base_path) + 1);
return array($path => $this);
} else {
$mappings = array();
foreach ($children as $child) {
$child_mappings = $child->getFragmentMappings(
$viewer,
$base_path);
foreach ($child_mappings as $key => $value) {
$mappings[$key] = $value;
}
}
return $mappings;
}
}
/* -( Policy Interface )--------------------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}

View file

@ -1,72 +0,0 @@
<?php
final class PhragmentFragmentVersion extends PhragmentDAO
implements PhabricatorPolicyInterface {
protected $sequence;
protected $fragmentPHID;
protected $filePHID;
private $fragment = self::ATTACHABLE;
private $file = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'sequence' => 'uint32',
'filePHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_version' => array(
'columns' => array('fragmentPHID', 'sequence'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhragmentFragmentVersionPHIDType::TYPECONST);
}
public function getURI() {
return '/phragment/version/'.$this->getID().'/';
}
public function getFragment() {
return $this->assertAttached($this->fragment);
}
public function attachFragment(PhragmentFragment $fragment) {
return $this->fragment = $fragment;
}
public function getFile() {
return $this->assertAttached($this->file);
}
public function attachFile(PhabricatorFile $file) {
return $this->file = $file;
}
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
return $this->getFragment()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getFragment()->hasAutomaticCapability($capability, $viewer);
}
public function describeAutomaticCapability($capability) {
return $this->getFragment()->describeAutomaticCapability($capability);
}
}

View file

@ -1,9 +0,0 @@
<?php
final class PhragmentSchemaSpec extends PhabricatorConfigSchemaSpec {
public function buildSchemata() {
$this->buildEdgeSchemata(new PhragmentFragment());
}
}

View file

@ -1,76 +0,0 @@
<?php
final class PhragmentSnapshot extends PhragmentDAO
implements PhabricatorPolicyInterface {
protected $primaryFragmentPHID;
protected $name;
private $primaryFragment = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text128',
),
self::CONFIG_KEY_SCHEMA => array(
'key_name' => array(
'columns' => array('primaryFragmentPHID', 'name'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhragmentSnapshotPHIDType::TYPECONST);
}
public function getURI() {
return '/phragment/snapshot/view/'.$this->getID().'/';
}
public function getPrimaryFragment() {
return $this->assertAttached($this->primaryFragment);
}
public function attachPrimaryFragment(PhragmentFragment $fragment) {
return $this->primaryFragment = $fragment;
}
public function delete() {
$children = id(new PhragmentSnapshotChild())
->loadAllWhere('snapshotPHID = %s', $this->getPHID());
$this->openTransaction();
foreach ($children as $child) {
$child->delete();
}
$result = parent::delete();
$this->saveTransaction();
return $result;
}
/* -( Policy Interface )--------------------------------------------------- */
public function getCapabilities() {
return $this->getPrimaryFragment()->getCapabilities();
}
public function getPolicy($capability) {
return $this->getPrimaryFragment()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getPrimaryFragment()
->hasAutomaticCapability($capability, $viewer);
}
public function describeAutomaticCapability($capability) {
return $this->getPrimaryFragment()
->describeAutomaticCapability($capability);
}
}

View file

@ -1,82 +0,0 @@
<?php
final class PhragmentSnapshotChild extends PhragmentDAO
implements PhabricatorPolicyInterface {
protected $snapshotPHID;
protected $fragmentPHID;
protected $fragmentVersionPHID;
private $snapshot = self::ATTACHABLE;
private $fragment = self::ATTACHABLE;
private $fragmentVersion = self::ATTACHABLE;
protected function getConfiguration() {
return array(
self::CONFIG_COLUMN_SCHEMA => array(
'fragmentVersionPHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_child' => array(
'columns' => array(
'snapshotPHID',
'fragmentPHID',
'fragmentVersionPHID',
),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getSnapshot() {
return $this->assertAttached($this->snapshot);
}
public function attachSnapshot(PhragmentSnapshot $snapshot) {
return $this->snapshot = $snapshot;
}
public function getFragment() {
return $this->assertAttached($this->fragment);
}
public function attachFragment(PhragmentFragment $fragment) {
return $this->fragment = $fragment;
}
public function getFragmentVersion() {
if ($this->fragmentVersionPHID === null) {
return null;
}
return $this->assertAttached($this->fragmentVersion);
}
public function attachFragmentVersion(PhragmentFragmentVersion $version) {
return $this->fragmentVersion = $version;
}
/* -( Policy Interface )--------------------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
return $this->getSnapshot()->getPolicy($capability);
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getSnapshot()
->hasAutomaticCapability($capability, $viewer);
}
public function describeAutomaticCapability($capability) {
return $this->getSnapshot()
->describeAutomaticCapability($capability);
}
}

View file

@ -1,53 +0,0 @@
<?php
final class PhragmentPatchUtil extends Phobject {
const EMPTY_HASH = '0000000000000000000000000000000000000000';
/**
* Calculate the DiffMatchPatch patch between two Phabricator files.
*
* @phutil-external-symbol class diff_match_patch
*/
public static function calculatePatch(
PhabricatorFile $old = null,
PhabricatorFile $new = null) {
$root = dirname(phutil_get_library_root('phabricator'));
require_once $root.'/externals/diff_match_patch/diff_match_patch.php';
$old_hash = self::EMPTY_HASH;
$new_hash = self::EMPTY_HASH;
if ($old !== null) {
$old_hash = $old->getContentHash();
}
if ($new !== null) {
$new_hash = $new->getContentHash();
}
$old_content = '';
$new_content = '';
if ($old_hash === $new_hash) {
return null;
}
if ($old_hash !== self::EMPTY_HASH) {
$old_content = $old->loadFileData();
} else {
$old_content = '';
}
if ($new_hash !== self::EMPTY_HASH) {
$new_content = $new->loadFileData();
} else {
$new_content = '';
}
$dmp = new diff_match_patch();
$dmp_patches = $dmp->patch_make($old_content, $new_content);
return $dmp->patch_toText($dmp_patches);
}
}

View file

@ -244,10 +244,6 @@
"name": "PHPAST",
"include": "(^src/applications/phpast/)"
},
"phragment": {
"name": "Phragment",
"include": "(^src/applications/phragment/)"
},
"phrequent": {
"name": "Phrequent",
"include": "(^src/applications/phrequent/)"

View file

@ -103,7 +103,6 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'db.policy' => array(),
'db.nuance' => array(),
'db.passphrase' => array(),
'db.phragment' => array(),
'db.dashboard' => array(),
'db.system' => array(),
'db.fund' => array(),