Summary: Ref T13455. Add container-level storage for persistent view state, and persist "Highlight As..." inside it. The storage generates a "PhabricatorChangesetViewState" configuration object as an output. When preferences are expressed on a diff and that diff is later attached to a revision, we attempt to copy the preferences. The internal storage tracks per-changeset settings, but currently always uses "last update wins" to apply the settings in the UI. Test Plan: - Viewed revisions, changed highlighting, reloaded. Saw highlighting stick in revision view and standalone view. - Viewed commits, changed highlighting, reloaded. Saw highlighting stick. - Created a diff, changed highlighting, turned it into a revision, saw highlighting persist. Subscribers: jmeador, PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T13455 Differential Revision: https://secure.phabricator.com/D21137
133 lines
3.1 KiB
PHP
133 lines
3.1 KiB
PHP
<?php
|
|
|
|
final class DifferentialViewState
|
|
extends DifferentialDAO
|
|
implements PhabricatorPolicyInterface {
|
|
|
|
protected $viewerPHID;
|
|
protected $objectPHID;
|
|
protected $viewState = array();
|
|
|
|
private $hasModifications;
|
|
|
|
protected function getConfiguration() {
|
|
return array(
|
|
self::CONFIG_SERIALIZATION => array(
|
|
'viewState' => self::SERIALIZATION_JSON,
|
|
),
|
|
self::CONFIG_KEY_SCHEMA => array(
|
|
'key_viewer' => array(
|
|
'columns' => array('viewerPHID', 'objectPHID'),
|
|
'unique' => true,
|
|
),
|
|
'key_object' => array(
|
|
'columns' => array('objectPHID'),
|
|
),
|
|
),
|
|
) + parent::getConfiguration();
|
|
}
|
|
|
|
public function setChangesetProperty(
|
|
DifferentialChangeset $changeset,
|
|
$key,
|
|
$value) {
|
|
|
|
if ($this->getChangesetProperty($changeset, $key) === $value) {
|
|
return;
|
|
}
|
|
|
|
$properties = array(
|
|
'value' => $value,
|
|
'epoch' => PhabricatorTime::getNow(),
|
|
);
|
|
|
|
$diff_id = $changeset->getDiffID();
|
|
if ($diff_id !== null) {
|
|
$properties['diffID'] = (int)$diff_id;
|
|
}
|
|
|
|
$path_hash = $this->getChangesetPathHash($changeset);
|
|
$changeset_phid = $this->getChangesetKey($changeset);
|
|
|
|
$this->hasModifications = true;
|
|
|
|
$this->viewState['changesets'][$path_hash][$key][$changeset_phid] =
|
|
$properties;
|
|
}
|
|
|
|
public function getChangesetProperty(
|
|
DifferentialChangeset $changeset,
|
|
$key,
|
|
$default = null) {
|
|
|
|
$path_hash = $this->getChangesetPathHash($changeset);
|
|
|
|
$entries = idxv($this->viewState, array('changesets', $path_hash, $key));
|
|
if (!is_array($entries)) {
|
|
$entries = array();
|
|
}
|
|
|
|
$entries = isort($entries, 'epoch');
|
|
|
|
$entry = last($entries);
|
|
if (!is_array($entry)) {
|
|
$entry = array();
|
|
}
|
|
|
|
return idx($entry, 'value', $default);
|
|
}
|
|
|
|
public function getHasModifications() {
|
|
return $this->hasModifications;
|
|
}
|
|
|
|
private function getChangesetPathHash(DifferentialChangeset $changeset) {
|
|
$path = $changeset->getFilename();
|
|
return PhabricatorHash::digestForIndex($path);
|
|
}
|
|
|
|
private function getChangesetKey(DifferentialChangeset $changeset) {
|
|
$key = $changeset->getID();
|
|
|
|
if ($key === null) {
|
|
return '*';
|
|
}
|
|
|
|
return (string)$key;
|
|
}
|
|
|
|
public static function copyViewStatesToObject($src_phid, $dst_phid) {
|
|
$table = new self();
|
|
$conn = $table->establishConnection('w');
|
|
|
|
queryfx(
|
|
$conn,
|
|
'INSERT IGNORE INTO %R
|
|
(viewerPHID, objectPHID, viewState, dateCreated, dateModified)
|
|
SELECT viewerPHID, %s, viewState, dateCreated, dateModified
|
|
FROM %R WHERE objectPHID = %s',
|
|
$table,
|
|
$dst_phid,
|
|
$table,
|
|
$src_phid);
|
|
}
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
public function getCapabilities() {
|
|
return array(
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
);
|
|
}
|
|
|
|
public function getPolicy($capability) {
|
|
return PhabricatorPolicies::POLICY_NOONE;
|
|
}
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
return ($viewer->getPHID() === $this->getViewerPHID());
|
|
}
|
|
|
|
}
|