Files
phabricator/src/applications/differential/storage/DifferentialViewState.php
epriestley 8aac55cc57 Make "Highlight As..." sticky across reloads in Diffusion and Differential
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
2020-04-19 08:58:39 -07:00

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());
}
}