Page MenuHomestyx hydra

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/applications/almanac/editor/AlmanacBindingEditEngine.php b/src/applications/almanac/editor/AlmanacBindingEditEngine.php
index 66db7fcbab..8de74b471b 100644
--- a/src/applications/almanac/editor/AlmanacBindingEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacBindingEditEngine.php
@@ -1,172 +1,172 @@
<?php
final class AlmanacBindingEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.binding';
private $service;
public function setService(AlmanacService $service) {
$this->service = $service;
return $this;
}
public function getService() {
if (!$this->service) {
throw new PhutilInvalidStateException('setService');
}
return $this->service;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Bindings');
}
public function getSummaryHeader() {
return pht('Edit Almanac Binding Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac bindings.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
$service = $this->getService();
return AlmanacBinding::initializeNewBinding($service);
}
protected function newEditableObjectForDocumentation() {
$service_type = AlmanacCustomServiceType::SERVICETYPE;
$service = AlmanacService::initializeNewService($service_type);
$this->setService($service);
return $this->newEditableObject();
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$service_phid = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'service') {
continue;
}
$service_phid = $raw_xaction['value'];
}
if ($service_phid === null) {
throw new Exception(
pht(
'When creating a new Almanac binding via the Conduit API, you '.
'must provide a "service" transaction to select a service to bind.'));
}
$service = id(new AlmanacServiceQuery())
->setViewer($this->getViewer())
->withPHIDs(array($service_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$service) {
throw new Exception(
pht(
'Service "%s" is unrecognized, restricted, or you do not have '.
'permission to edit it.',
$service_phid));
}
$this->setService($service);
return $this->newEditableObject();
}
protected function newObjectQuery() {
return id(new AlmanacBindingQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Binding');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Binding');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Binding');
}
protected function getObjectEditShortText($object) {
return pht('Edit Binding');
}
protected function getObjectCreateShortText() {
return pht('Create Binding');
}
protected function getObjectName() {
return pht('Binding');
}
protected function getEditorURI() {
return '/almanac/binding/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/binding/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('service')
->setLabel(pht('Service'))
->setIsFormField(false)
->setTransactionType(
AlmanacBindingServiceTransaction::TRANSACTIONTYPE)
->setDescription(pht('Service to create a binding for.'))
->setConduitDescription(pht('Select the service to bind.'))
->setConduitTypeDescription(pht('Service PHID.'))
->setValue($object->getServicePHID()),
id(new PhabricatorTextEditField())
->setKey('interface')
->setLabel(pht('Interface'))
->setIsFormField(false)
->setTransactionType(
AlmanacBindingInterfaceTransaction::TRANSACTIONTYPE)
->setDescription(pht('Interface to bind the service to.'))
->setConduitDescription(pht('Set the interface to bind.'))
->setConduitTypeDescription(pht('Interface PHID.'))
->setValue($object->getInterfacePHID()),
id(new PhabricatorBoolEditField())
->setKey('disabled')
->setLabel(pht('Disabled'))
->setIsFormField(false)
->setTransactionType(
AlmanacBindingDisableTransaction::TRANSACTIONTYPE)
->setDescription(pht('Disable or enable the binding.'))
->setConduitDescription(pht('Disable or enable the binding.'))
->setConduitTypeDescription(pht('True to disable the binding.'))
->setValue($object->getIsDisabled())
->setOptions(
pht('Enable Binding'),
pht('Disable Binding')),
);
}
}
diff --git a/src/applications/almanac/editor/AlmanacDeviceEditEngine.php b/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
index d0c2b48f7a..e6d1b55d2e 100644
--- a/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
@@ -1,117 +1,117 @@
<?php
final class AlmanacDeviceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.device';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Devices');
}
public function getSummaryHeader() {
return pht('Edit Almanac Device Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac devices.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
return AlmanacDevice::initializeNewDevice();
}
protected function newObjectQuery() {
return id(new AlmanacDeviceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Device');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Device');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Device: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Device');
}
protected function getObjectCreateShortText() {
return pht('Create Device');
}
protected function getObjectName() {
return pht('Device');
}
protected function getEditorURI() {
return '/almanac/device/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/device/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AlmanacCreateDevicesCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$status_map = $this->getDeviceStatusMap($object);
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the device.'))
->setTransactionType(AlmanacDeviceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setDescription(pht('Device status.'))
->setTransactionType(AlmanacDeviceStatusTransaction::TRANSACTIONTYPE)
->setOptions($status_map)
->setValue($object->getStatus()),
);
}
private function getDeviceStatusMap(AlmanacDevice $device) {
$status_map = AlmanacDeviceStatus::getStatusMap();
// If the device currently has an unknown status, add it to the list for
// the dropdown.
$status_value = $device->getStatus();
if (!isset($status_map[$status_value])) {
$status_map = array(
$status_value => AlmanacDeviceStatus::newStatusFromValue($status_value),
) + $status_map;
}
$status_map = mpull($status_map, 'getName');
return $status_map;
}
}
diff --git a/src/applications/almanac/editor/AlmanacEditor.php b/src/applications/almanac/editor/AlmanacEditor.php
index 54c32c79cd..4f92a748d2 100644
--- a/src/applications/almanac/editor/AlmanacEditor.php
+++ b/src/applications/almanac/editor/AlmanacEditor.php
@@ -1,10 +1,10 @@
<?php
abstract class AlmanacEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/editor/AlmanacInterfaceEditEngine.php b/src/applications/almanac/editor/AlmanacInterfaceEditEngine.php
index ca57113bf2..0cf3df229e 100644
--- a/src/applications/almanac/editor/AlmanacInterfaceEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacInterfaceEditEngine.php
@@ -1,186 +1,186 @@
<?php
final class AlmanacInterfaceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.interface';
private $device;
public function setDevice(AlmanacDevice $device) {
$this->device = $device;
return $this;
}
public function getDevice() {
if (!$this->device) {
throw new PhutilInvalidStateException('setDevice');
}
return $this->device;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Interfaces');
}
public function getSummaryHeader() {
return pht('Edit Almanac Interface Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac interfaces.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
$interface = AlmanacInterface::initializeNewInterface();
$device = $this->getDevice();
$interface
->setDevicePHID($device->getPHID())
->attachDevice($device);
return $interface;
}
protected function newEditableObjectForDocumentation() {
$this->setDevice(new AlmanacDevice());
return $this->newEditableObject();
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$device_phid = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'device') {
continue;
}
$device_phid = $raw_xaction['value'];
}
if ($device_phid === null) {
throw new Exception(
pht(
'When creating a new Almanac interface via the Conduit API, you '.
'must provide a "device" transaction to select a device.'));
}
$device = id(new AlmanacDeviceQuery())
->setViewer($this->getViewer())
->withPHIDs(array($device_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$device) {
throw new Exception(
pht(
'Device "%s" is unrecognized, restricted, or you do not have '.
'permission to edit it.',
$device_phid));
}
$this->setDevice($device);
return $this->newEditableObject();
}
protected function newObjectQuery() {
return new AlmanacInterfaceQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Interface');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Interface');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Interface');
}
protected function getObjectEditShortText($object) {
return pht('Edit Interface');
}
protected function getObjectCreateShortText() {
return pht('Create Interface');
}
protected function getObjectName() {
return pht('Interface');
}
protected function getEditorURI() {
return '/almanac/interface/edit/';
}
protected function getObjectCreateCancelURI($object) {
if ($this->getDevice()) {
return $this->getDevice()->getURI();
}
return '/almanac/interface/';
}
protected function getObjectViewURI($object) {
return $object->getDevice()->getURI();
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
// TODO: Some day, this should be a datasource.
$networks = id(new AlmanacNetworkQuery())
->setViewer($viewer)
->execute();
$network_map = mpull($networks, 'getName', 'getPHID');
return array(
id(new PhabricatorTextEditField())
->setKey('device')
->setLabel(pht('Device'))
->setIsFormField(false)
->setTransactionType(
AlmanacInterfaceDeviceTransaction::TRANSACTIONTYPE)
->setDescription(pht('When creating an interface, set the device.'))
->setConduitDescription(pht('Set the device.'))
->setConduitTypeDescription(pht('Device PHID.'))
->setValue($object->getDevicePHID()),
id(new PhabricatorSelectEditField())
->setKey('network')
->setLabel(pht('Network'))
->setDescription(pht('Network for the interface.'))
->setTransactionType(
AlmanacInterfaceNetworkTransaction::TRANSACTIONTYPE)
->setValue($object->getNetworkPHID())
->setOptions($network_map),
id(new PhabricatorTextEditField())
->setKey('address')
->setLabel(pht('Address'))
->setDescription(pht('Address of the service.'))
->setTransactionType(
AlmanacInterfaceAddressTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getAddress()),
id(new PhabricatorIntEditField())
->setKey('port')
->setLabel(pht('Port'))
->setDescription(pht('Port of the service.'))
->setTransactionType(AlmanacInterfacePortTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getPort()),
);
}
}
diff --git a/src/applications/almanac/editor/AlmanacNamespaceEditEngine.php b/src/applications/almanac/editor/AlmanacNamespaceEditEngine.php
index cf6ad36c00..fe22d4f14c 100644
--- a/src/applications/almanac/editor/AlmanacNamespaceEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacNamespaceEditEngine.php
@@ -1,90 +1,90 @@
<?php
final class AlmanacNamespaceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.namespace';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Namespaces');
}
public function getSummaryHeader() {
return pht('Edit Almanac Namespace Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac namespaces.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
return AlmanacNamespace::initializeNewNamespace();
}
protected function newObjectQuery() {
return new AlmanacNamespaceQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Namespace');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Namespace');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Namespace: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Namespace');
}
protected function getObjectCreateShortText() {
return pht('Create Namespace');
}
protected function getObjectName() {
return pht('Namespace');
}
protected function getEditorURI() {
return '/almanac/namespace/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/namespace/';
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return "/almanac/namespace/{$id}/";
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AlmanacCreateNamespacesCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the namespace.'))
->setTransactionType(AlmanacNamespaceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);
}
}
diff --git a/src/applications/almanac/editor/AlmanacNetworkEditEngine.php b/src/applications/almanac/editor/AlmanacNetworkEditEngine.php
index 027b2a9aa0..600ead5b05 100644
--- a/src/applications/almanac/editor/AlmanacNetworkEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacNetworkEditEngine.php
@@ -1,90 +1,90 @@
<?php
final class AlmanacNetworkEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.network';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Networks');
}
public function getSummaryHeader() {
return pht('Edit Almanac Network Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac networks.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
return AlmanacNetwork::initializeNewNetwork();
}
protected function newObjectQuery() {
return new AlmanacNetworkQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Network');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Network');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Network: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Network');
}
protected function getObjectCreateShortText() {
return pht('Create Network');
}
protected function getObjectName() {
return pht('Network');
}
protected function getEditorURI() {
return '/almanac/network/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/network/';
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return "/almanac/network/{$id}/";
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AlmanacCreateNetworksCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the network.'))
->setTransactionType(AlmanacNetworkNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);
}
}
diff --git a/src/applications/almanac/editor/AlmanacPropertyEditEngine.php b/src/applications/almanac/editor/AlmanacPropertyEditEngine.php
index 38139f79fa..999b7af9f4 100644
--- a/src/applications/almanac/editor/AlmanacPropertyEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacPropertyEditEngine.php
@@ -1,86 +1,86 @@
<?php
abstract class AlmanacPropertyEditEngine
extends PhabricatorEditEngine {
private $propertyKey;
public function setPropertyKey($property_key) {
$this->propertyKey = $property_key;
return $this;
}
public function getPropertyKey() {
return $this->propertyKey;
}
public function isEngineConfigurable() {
return false;
}
public function isEngineExtensible() {
return false;
}
public function getEngineName() {
return pht('Almanac Properties');
}
public function getSummaryHeader() {
return pht('Edit Almanac Property Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac properties.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
throw new PhutilMethodNotImplementedException();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Property');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Property');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Property: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Property');
}
protected function getObjectCreateShortText() {
return pht('Create Property');
}
protected function buildCustomEditFields($object) {
$property_key = $this->getPropertyKey();
$xaction_type = $object->getAlmanacPropertySetTransactionType();
$specs = $object->getAlmanacPropertyFieldSpecifications();
if (isset($specs[$property_key])) {
$field_template = clone $specs[$property_key];
} else {
$field_template = new PhabricatorTextEditField();
}
return array(
$field_template
->setKey('value')
->setMetadataValue('almanac.property', $property_key)
->setLabel($property_key)
->setTransactionType($xaction_type)
->setValue($object->getAlmanacPropertyValue($property_key)),
);
}
}
diff --git a/src/applications/almanac/editor/AlmanacServiceEditEngine.php b/src/applications/almanac/editor/AlmanacServiceEditEngine.php
index b63075543f..e0c4086d2e 100644
--- a/src/applications/almanac/editor/AlmanacServiceEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacServiceEditEngine.php
@@ -1,149 +1,149 @@
<?php
final class AlmanacServiceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.service';
private $serviceType;
public function setServiceType($service_type) {
$this->serviceType = $service_type;
return $this;
}
public function getServiceType() {
return $this->serviceType;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Services');
}
public function getSummaryHeader() {
return pht('Edit Almanac Service Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac services.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function newEditableObject() {
$service_type = $this->getServiceType();
return AlmanacService::initializeNewService($service_type);
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$type = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'type') {
continue;
}
$type = $raw_xaction['value'];
}
if ($type === null) {
throw new Exception(
pht(
'When creating a new Almanac service via the Conduit API, you '.
'must provide a "type" transaction to select a type.'));
}
$map = AlmanacServiceType::getAllServiceTypes();
if (!isset($map[$type])) {
throw new Exception(
pht(
'Service type "%s" is unrecognized. Valid types are: %s.',
$type,
implode(', ', array_keys($map))));
}
$this->setServiceType($type);
return $this->newEditableObject();
}
protected function newEditableObjectForDocumentation() {
$service_type = new AlmanacCustomServiceType();
$this->setServiceType($service_type->getServiceTypeConstant());
return $this->newEditableObject();
}
protected function newObjectQuery() {
return id(new AlmanacServiceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Service');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Service');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Service: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Service');
}
protected function getObjectCreateShortText() {
return pht('Create Service');
}
protected function getObjectName() {
return pht('Service');
}
protected function getEditorURI() {
return '/almanac/service/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/service/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AlmanacCreateServicesCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the service.'))
->setTransactionType(AlmanacServiceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('type')
->setLabel(pht('Type'))
->setIsFormField(false)
->setTransactionType(
AlmanacServiceTypeTransaction::TRANSACTIONTYPE)
->setDescription(pht('When creating a service, set the type.'))
->setConduitDescription(pht('Set the service type.'))
->setConduitTypeDescription(pht('Service type.'))
->setValue($object->getServiceType()),
);
}
}
diff --git a/src/applications/almanac/phid/AlmanacBindingPHIDType.php b/src/applications/almanac/phid/AlmanacBindingPHIDType.php
index db469690cd..5f0da9b491 100644
--- a/src/applications/almanac/phid/AlmanacBindingPHIDType.php
+++ b/src/applications/almanac/phid/AlmanacBindingPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class AlmanacBindingPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ABND';
public function getTypeName() {
return pht('Almanac Binding');
}
public function newObject() {
return new AlmanacBinding();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacBindingQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$binding = $objects[$phid];
$id = $binding->getID();
$handle->setObjectName(pht('Binding %d', $id));
$handle->setName(pht('Binding %d', $id));
}
}
}
diff --git a/src/applications/almanac/phid/AlmanacDevicePHIDType.php b/src/applications/almanac/phid/AlmanacDevicePHIDType.php
index 26c88a7a86..31be5eade2 100644
--- a/src/applications/almanac/phid/AlmanacDevicePHIDType.php
+++ b/src/applications/almanac/phid/AlmanacDevicePHIDType.php
@@ -1,44 +1,44 @@
<?php
final class AlmanacDevicePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ADEV';
public function getTypeName() {
return pht('Almanac Device');
}
public function newObject() {
return new AlmanacDevice();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacDeviceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$device = $objects[$phid];
$id = $device->getID();
$name = $device->getName();
$handle->setObjectName(pht('Device %d', $id));
$handle->setName($name);
$handle->setURI($device->getURI());
}
}
}
diff --git a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
index c7fe73183a..50b1d3ca4d 100644
--- a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
+++ b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
@@ -1,59 +1,59 @@
<?php
final class AlmanacInterfacePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AINT';
public function getTypeName() {
return pht('Almanac Interface');
}
public function newObject() {
return new AlmanacInterface();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacInterfaceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$interface = $objects[$phid];
$id = $interface->getID();
$device = $interface->getDevice();
$device_name = $device->getName();
$address = $interface->getAddress();
$port = $interface->getPort();
$network = $interface->getNetwork()->getName();
$name = pht(
'%s:%s (%s on %s)',
$device_name,
$port,
$address,
$network);
$handle->setObjectName(pht('Interface %d', $id));
$handle->setName($name);
if ($device->isDisabled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/almanac/phid/AlmanacNamespacePHIDType.php b/src/applications/almanac/phid/AlmanacNamespacePHIDType.php
index aa0b8fc4ef..71a8a6b475 100644
--- a/src/applications/almanac/phid/AlmanacNamespacePHIDType.php
+++ b/src/applications/almanac/phid/AlmanacNamespacePHIDType.php
@@ -1,44 +1,44 @@
<?php
final class AlmanacNamespacePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ANAM';
public function getTypeName() {
return pht('Almanac Namespace');
}
public function newObject() {
return new AlmanacNamespace();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacNamespaceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$namespace = $objects[$phid];
$id = $namespace->getID();
$name = $namespace->getName();
$handle->setObjectName(pht('Namespace %d', $id));
$handle->setName($name);
$handle->setURI($namespace->getURI());
}
}
}
diff --git a/src/applications/almanac/phid/AlmanacNetworkPHIDType.php b/src/applications/almanac/phid/AlmanacNetworkPHIDType.php
index 2264ce0e5f..3aa4f1a24b 100644
--- a/src/applications/almanac/phid/AlmanacNetworkPHIDType.php
+++ b/src/applications/almanac/phid/AlmanacNetworkPHIDType.php
@@ -1,44 +1,44 @@
<?php
final class AlmanacNetworkPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ANET';
public function getTypeName() {
return pht('Almanac Network');
}
public function newObject() {
return new AlmanacNetwork();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacNetworkQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$network = $objects[$phid];
$id = $network->getID();
$name = $network->getName();
$handle->setObjectName(pht('Network %d', $id));
$handle->setName($name);
$handle->setURI($network->getURI());
}
}
}
diff --git a/src/applications/almanac/phid/AlmanacServicePHIDType.php b/src/applications/almanac/phid/AlmanacServicePHIDType.php
index a64a229e94..fdc48706d4 100644
--- a/src/applications/almanac/phid/AlmanacServicePHIDType.php
+++ b/src/applications/almanac/phid/AlmanacServicePHIDType.php
@@ -1,44 +1,44 @@
<?php
final class AlmanacServicePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ASRV';
public function getTypeName() {
return pht('Almanac Service');
}
public function newObject() {
return new AlmanacService();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new AlmanacServiceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$service = $objects[$phid];
$id = $service->getID();
$name = $service->getName();
$handle->setObjectName(pht('Service %d', $id));
$handle->setName($name);
$handle->setURI($service->getURI());
}
}
}
diff --git a/src/applications/almanac/query/AlmanacBindingSearchEngine.php b/src/applications/almanac/query/AlmanacBindingSearchEngine.php
index fbeb7644b9..053cc2cd34 100644
--- a/src/applications/almanac/query/AlmanacBindingSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacBindingSearchEngine.php
@@ -1,80 +1,80 @@
<?php
final class AlmanacBindingSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Bindings');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacBindingQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Services'))
->setKey('servicePHIDs')
->setAliases(array('service', 'servicePHID', 'services'))
->setDescription(pht('Search for bindings on particular services.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setAliases(array('device', 'devicePHID', 'devices'))
->setDescription(pht('Search for bindings on particular devices.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['servicePHIDs']) {
$query->withServicePHIDs($map['servicePHIDs']);
}
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/binding/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Bindings'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $devices,
PhabricatorSavedQuery $query,
array $handles) {
// For now, this SearchEngine just supports API access via Conduit.
throw new PhutilMethodNotImplementedException();
}
}
diff --git a/src/applications/almanac/query/AlmanacDeviceQuery.php b/src/applications/almanac/query/AlmanacDeviceQuery.php
index 42796c4839..47006cb756 100644
--- a/src/applications/almanac/query/AlmanacDeviceQuery.php
+++ b/src/applications/almanac/query/AlmanacDeviceQuery.php
@@ -1,154 +1,154 @@
<?php
final class AlmanacDeviceQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $names;
private $namePrefix;
private $nameSuffix;
private $isClusterDevice;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNamePrefix($prefix) {
$this->namePrefix = $prefix;
return $this;
}
public function withNameSuffix($suffix) {
$this->nameSuffix = $suffix;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new AlmanacDeviceNameNgrams(),
$ngrams);
}
public function withIsClusterDevice($is_cluster_device) {
$this->isClusterDevice = $is_cluster_device;
return $this;
}
public function newResultObject() {
return new AlmanacDevice();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'device.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'device.phid IN (%Ls)',
$this->phids);
}
if ($this->names !== null) {
$hashes = array();
foreach ($this->names as $name) {
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn,
'device.nameIndex IN (%Ls)',
$hashes);
}
if ($this->namePrefix !== null) {
$where[] = qsprintf(
$conn,
'device.name LIKE %>',
$this->namePrefix);
}
if ($this->nameSuffix !== null) {
$where[] = qsprintf(
$conn,
'device.name LIKE %<',
$this->nameSuffix);
}
if ($this->isClusterDevice !== null) {
$where[] = qsprintf(
$conn,
'device.isBoundToClusterService = %d',
(int)$this->isClusterDevice);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'device.status IN (%Ls)',
$this->statuses);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'device';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'type' => 'string',
'unique' => true,
'reverse' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Device Name'),
),
) + parent::getBuiltinOrders();
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
index 9f98abb292..86633ac870 100644
--- a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
@@ -1,140 +1,140 @@
<?php
final class AlmanacDeviceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Devices');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacDeviceQuery();
}
protected function buildCustomSearchFields() {
$status_options = AlmanacDeviceStatus::getStatusMap();
$status_options = mpull($status_options, 'getName');
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for devices by name substring.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Exact Names'))
->setKey('names')
->setDescription(pht('Search for devices with specific names.')),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setDescription(pht('Search for devices with given statuses.'))
->setOptions($status_options),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Cluster Device'))
->setKey('isClusterDevice')
->setOptions(
pht('Both Cluster and Non-cluster Devices'),
pht('Cluster Devices Only'),
pht('Non-cluster Devices Only')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['names']) {
$query->withNames($map['names']);
}
if ($map['isClusterDevice'] !== null) {
$query->withIsClusterDevice($map['isClusterDevice']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/device/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Devices'),
'all' => pht('All Devices'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
$active_statuses = AlmanacDeviceStatus::getActiveStatusList();
return $query->setParameter('statuses', $active_statuses);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $devices,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($devices, 'AlmanacDevice');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($devices as $device) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Device %d', $device->getID()))
->setHeader($device->getName())
->setHref($device->getURI())
->setObject($device);
if ($device->isClusterDevice()) {
$item->addIcon('fa-sitemap', pht('Cluster Device'));
}
if ($device->isDisabled()) {
$item->setDisabled(true);
}
$status = $device->getStatusObject();
$icon_icon = $status->getIconIcon();
$icon_color = $status->getIconColor();
$icon_label = $status->getName();
$item->setStatusIcon(
"{$icon_icon} {$icon_color}",
$icon_label);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No Almanac Devices found.'));
return $result;
}
}
diff --git a/src/applications/almanac/query/AlmanacInterfaceQuery.php b/src/applications/almanac/query/AlmanacInterfaceQuery.php
index dbbc0cd53e..88eb9c2d74 100644
--- a/src/applications/almanac/query/AlmanacInterfaceQuery.php
+++ b/src/applications/almanac/query/AlmanacInterfaceQuery.php
@@ -1,207 +1,207 @@
<?php
final class AlmanacInterfaceQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $networkPHIDs;
private $devicePHIDs;
private $addresses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNetworkPHIDs(array $phids) {
$this->networkPHIDs = $phids;
return $this;
}
public function withDevicePHIDs(array $phids) {
$this->devicePHIDs = $phids;
return $this;
}
public function withAddresses(array $addresses) {
$this->addresses = $addresses;
return $this;
}
public function newResultObject() {
return new AlmanacInterface();
}
protected function willFilterPage(array $interfaces) {
$network_phids = mpull($interfaces, 'getNetworkPHID');
$device_phids = mpull($interfaces, 'getDevicePHID');
$networks = id(new AlmanacNetworkQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($network_phids)
->needProperties($this->getNeedProperties())
->execute();
$networks = mpull($networks, null, 'getPHID');
$devices = id(new AlmanacDeviceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($device_phids)
->needProperties($this->getNeedProperties())
->execute();
$devices = mpull($devices, null, 'getPHID');
foreach ($interfaces as $key => $interface) {
$network = idx($networks, $interface->getNetworkPHID());
$device = idx($devices, $interface->getDevicePHID());
if (!$network || !$device) {
$this->didRejectResult($interface);
unset($interfaces[$key]);
continue;
}
$interface->attachNetwork($network);
$interface->attachDevice($device);
}
return $interfaces;
}
protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
$select = parent::buildSelectClauseParts($conn);
if ($this->shouldJoinDeviceTable()) {
$select[] = qsprintf($conn, 'device.name');
}
return $select;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'interface.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'interface.phid IN (%Ls)',
$this->phids);
}
if ($this->networkPHIDs !== null) {
$where[] = qsprintf(
$conn,
'interface.networkPHID IN (%Ls)',
$this->networkPHIDs);
}
if ($this->devicePHIDs !== null) {
$where[] = qsprintf(
$conn,
'interface.devicePHID IN (%Ls)',
$this->devicePHIDs);
}
if ($this->addresses !== null) {
$parts = array();
foreach ($this->addresses as $address) {
$parts[] = qsprintf(
$conn,
'(interface.networkPHID = %s '.
'AND interface.address = %s '.
'AND interface.port = %d)',
$address->getNetworkPHID(),
$address->getAddress(),
$address->getPort());
}
$where[] = qsprintf($conn, '%LO', $parts);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinDeviceTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T device ON device.phid = interface.devicePHID',
id(new AlmanacDevice())->getTableName());
}
return $joins;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinDeviceTable()) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
private function shouldJoinDeviceTable() {
$vector = $this->getOrderVector();
if ($vector->containsKey('name')) {
return true;
}
return false;
}
protected function getPrimaryTableAlias() {
return 'interface';
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Device Name'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => 'device',
'column' => 'name',
'type' => 'string',
'reverse' => true,
),
);
}
protected function newPagingMapFromCursorObject(
PhabricatorQueryCursor $cursor,
array $keys) {
$interface = $cursor->getObject();
return array(
'id' => (int)$interface->getID(),
'name' => $cursor->getRawRowProperty('device.name'),
);
}
}
diff --git a/src/applications/almanac/query/AlmanacInterfaceSearchEngine.php b/src/applications/almanac/query/AlmanacInterfaceSearchEngine.php
index 9a3c5bc8f0..740affd526 100644
--- a/src/applications/almanac/query/AlmanacInterfaceSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacInterfaceSearchEngine.php
@@ -1,71 +1,71 @@
<?php
final class AlmanacInterfaceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Interfaces');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacInterfaceQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setAliases(array('device', 'devicePHID', 'devices'))
->setDescription(pht('Search for interfaces on particular devices.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/interface/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Interfaces'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $devices,
PhabricatorSavedQuery $query,
array $handles) {
// For now, this SearchEngine just supports API access via Conduit.
throw new PhutilMethodNotImplementedException();
}
}
diff --git a/src/applications/almanac/query/AlmanacNamespaceQuery.php b/src/applications/almanac/query/AlmanacNamespaceQuery.php
index e6c99bf6ea..58ba54f74a 100644
--- a/src/applications/almanac/query/AlmanacNamespaceQuery.php
+++ b/src/applications/almanac/query/AlmanacNamespaceQuery.php
@@ -1,98 +1,98 @@
<?php
final class AlmanacNamespaceQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new AlmanacNamespaceNameNgrams(),
$ngrams);
}
public function newResultObject() {
return new AlmanacNamespace();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'namespace.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'namespace.phid IN (%Ls)',
$this->phids);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'namespace.name IN (%Ls)',
$this->names);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'namespace';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'type' => 'string',
'unique' => true,
'reverse' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Namespace Name'),
),
) + parent::getBuiltinOrders();
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/query/AlmanacNamespaceSearchEngine.php b/src/applications/almanac/query/AlmanacNamespaceSearchEngine.php
index 14a96d22a0..a4658c5f33 100644
--- a/src/applications/almanac/query/AlmanacNamespaceSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacNamespaceSearchEngine.php
@@ -1,90 +1,90 @@
<?php
final class AlmanacNamespaceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Namespaces');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacNamespaceQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for namespaces by name substring.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/namespace/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Namespaces'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $namespaces,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($namespaces, 'AlmanacNamespace');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($namespaces as $namespace) {
$id = $namespace->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Namespace %d', $id))
->setHeader($namespace->getName())
->setHref($this->getApplicationURI("namespace/{$id}/"))
->setObject($namespace);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No Almanac namespaces found.'));
return $result;
}
}
diff --git a/src/applications/almanac/query/AlmanacNetworkQuery.php b/src/applications/almanac/query/AlmanacNetworkQuery.php
index 7af9db8585..a688fedda9 100644
--- a/src/applications/almanac/query/AlmanacNetworkQuery.php
+++ b/src/applications/almanac/query/AlmanacNetworkQuery.php
@@ -1,70 +1,70 @@
<?php
final class AlmanacNetworkQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function newResultObject() {
return new AlmanacNetwork();
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new AlmanacNetworkNameNgrams(),
$ngrams);
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'network.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'network.phid IN (%Ls)',
$this->phids);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'network.name IN (%Ls)',
$this->names);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'network';
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/query/AlmanacNetworkSearchEngine.php b/src/applications/almanac/query/AlmanacNetworkSearchEngine.php
index 53f9b24e44..5938fd44c7 100644
--- a/src/applications/almanac/query/AlmanacNetworkSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacNetworkSearchEngine.php
@@ -1,90 +1,90 @@
<?php
final class AlmanacNetworkSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Networks');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacNetworkQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for networks by name substring.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/network/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Networks'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $networks,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($networks, 'AlmanacNetwork');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($networks as $network) {
$id = $network->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Network %d', $id))
->setHeader($network->getName())
->setHref($this->getApplicationURI("network/{$id}/"))
->setObject($network);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No Almanac Networks found.'));
return $result;
}
}
diff --git a/src/applications/almanac/query/AlmanacPropertyQuery.php b/src/applications/almanac/query/AlmanacPropertyQuery.php
index 4261c70fec..8c93d4d70b 100644
--- a/src/applications/almanac/query/AlmanacPropertyQuery.php
+++ b/src/applications/almanac/query/AlmanacPropertyQuery.php
@@ -1,105 +1,105 @@
<?php
final class AlmanacPropertyQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
private $objects;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function withObjects(array $objects) {
$this->objects = mpull($objects, null, 'getPHID');
$this->objectPHIDs = array_keys($this->objects);
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function newResultObject() {
return new AlmanacProperty();
}
protected function willFilterPage(array $properties) {
$object_phids = mpull($properties, 'getObjectPHID');
$object_phids = array_fuse($object_phids);
if ($this->objects !== null) {
$object_phids = array_diff_key($object_phids, $this->objects);
}
if ($object_phids) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
$objects += $this->objects;
foreach ($properties as $key => $property) {
$object = idx($objects, $property->getObjectPHID());
if (!$object) {
unset($properties[$key]);
continue;
}
$property->attachObject($object);
}
return $properties;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->names !== null) {
$hashes = array();
foreach ($this->names as $name) {
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn,
'fieldIndex IN (%Ls)',
$hashes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/query/AlmanacQuery.php b/src/applications/almanac/query/AlmanacQuery.php
index b5b6146c7f..8b2bc894e8 100644
--- a/src/applications/almanac/query/AlmanacQuery.php
+++ b/src/applications/almanac/query/AlmanacQuery.php
@@ -1,61 +1,61 @@
<?php
abstract class AlmanacQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $needProperties;
public function needProperties($need_properties) {
$this->needProperties = $need_properties;
return $this;
}
protected function getNeedProperties() {
return $this->needProperties;
}
protected function didFilterPage(array $objects) {
$has_properties = (head($objects) instanceof AlmanacPropertyInterface);
if ($has_properties && $this->needProperties) {
$property_query = id(new AlmanacPropertyQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withObjects($objects);
$properties = $property_query->execute();
$properties = mgroup($properties, 'getObjectPHID');
foreach ($objects as $object) {
$object_properties = idx($properties, $object->getPHID(), array());
$object_properties = mpull($object_properties, null, 'getFieldName');
// Create synthetic properties for defaults on the object itself.
$specs = $object->getAlmanacPropertyFieldSpecifications();
foreach ($specs as $key => $spec) {
if (empty($object_properties[$key])) {
$default_value = $spec->getValueForTransaction();
$object_properties[$key] = id(new AlmanacProperty())
->setObjectPHID($object->getPHID())
->setFieldName($key)
->setFieldValue($default_value);
}
}
foreach ($object_properties as $property) {
$property->attachObject($object);
}
$object->attachAlmanacProperties($object_properties);
}
}
return $objects;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
}
diff --git a/src/applications/almanac/query/AlmanacServiceSearchEngine.php b/src/applications/almanac/query/AlmanacServiceSearchEngine.php
index a2fd9c23b7..f9786a87d2 100644
--- a/src/applications/almanac/query/AlmanacServiceSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacServiceSearchEngine.php
@@ -1,118 +1,118 @@
<?php
final class AlmanacServiceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Services');
}
public function getApplicationClassName() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function newQuery() {
return new AlmanacServiceQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['names']) {
$query->withNames($map['names']);
}
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
if ($map['serviceTypes']) {
$query->withServiceTypes($map['serviceTypes']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for services by name substring.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Exact Names'))
->setKey('names')
->setDescription(pht('Search for services with specific names.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Service Types'))
->setKey('serviceTypes')
->setDescription(pht('Find services by type.'))
->setDatasource(id(new AlmanacServiceTypeDatasource())),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setDescription(
pht('Search for services bound to particular devices.')),
);
}
protected function getURI($path) {
return '/almanac/service/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Services'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $services,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($services, 'AlmanacService');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($services as $service) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Service %d', $service->getID()))
->setHeader($service->getName())
->setHref($service->getURI())
->setObject($service)
->addIcon(
$service->getServiceImplementation()->getServiceTypeIcon(),
$service->getServiceImplementation()->getServiceTypeShortName());
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No Almanac Services found.'));
return $result;
}
}
diff --git a/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php b/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
index dca5dd986b..8666265d27 100644
--- a/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
+++ b/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
@@ -1,64 +1,64 @@
<?php
final class AlmanacInterfaceDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Interfaces');
}
public function getPlaceholderText() {
return pht('Type an interface name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$devices = id(new AlmanacDeviceQuery())
->setViewer($viewer)
->withNamePrefix($raw_query)
->execute();
if ($devices) {
$interface_query = id(new AlmanacInterfaceQuery())
->setViewer($viewer)
->withDevicePHIDs(mpull($devices, 'getPHID'))
->setOrder('name');
$interfaces = $this->executeQuery($interface_query);
} else {
$interfaces = array();
}
if ($interfaces) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($interfaces, 'getPHID'))
->execute();
} else {
$handles = array();
}
$results = array();
foreach ($handles as $handle) {
if ($handle->isClosed()) {
$closed = pht('Disabled');
} else {
$closed = null;
}
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
->setPHID($handle->getPHID())
->setClosed($closed);
}
return $results;
}
}
diff --git a/src/applications/almanac/typeahead/AlmanacServiceDatasource.php b/src/applications/almanac/typeahead/AlmanacServiceDatasource.php
index 4413465125..d5f990ce47 100644
--- a/src/applications/almanac/typeahead/AlmanacServiceDatasource.php
+++ b/src/applications/almanac/typeahead/AlmanacServiceDatasource.php
@@ -1,57 +1,57 @@
<?php
final class AlmanacServiceDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Services');
}
public function getPlaceholderText() {
return pht('Type a service name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$services = id(new AlmanacServiceQuery())
->withNamePrefix($raw_query)
->setOrder('name');
// TODO: When service classes are restricted, it might be nice to customize
// the title and placeholder text to show which service types can be
// selected, or show all services but mark the invalid ones disabled and
// prevent their selection.
$service_types = $this->getParameter('serviceTypes');
if ($service_types) {
$services->withServiceTypes($service_types);
}
$services = $this->executeQuery($services);
if ($services) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($services, 'getPHID'))
->execute();
} else {
$handles = array();
}
$results = array();
foreach ($handles as $handle) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
->setPHID($handle->getPHID());
}
return $results;
}
}
diff --git a/src/applications/almanac/typeahead/AlmanacServiceTypeDatasource.php b/src/applications/almanac/typeahead/AlmanacServiceTypeDatasource.php
index 5314084244..b0b81baed9 100644
--- a/src/applications/almanac/typeahead/AlmanacServiceTypeDatasource.php
+++ b/src/applications/almanac/typeahead/AlmanacServiceTypeDatasource.php
@@ -1,43 +1,43 @@
<?php
final class AlmanacServiceTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Service Types');
}
public function getPlaceholderText() {
return pht('Type a service type name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorAlmanacApplication';
+ return PhabricatorAlmanacApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$types = AlmanacServiceType::getAllServiceTypes();
$results = array();
foreach ($types as $key => $type) {
$results[$key] = id(new PhabricatorTypeaheadResult())
->setName($type->getServiceTypeName())
->setIcon($type->getServiceTypeIcon())
->setPHID($key);
}
return $results;
}
}
diff --git a/src/applications/audit/editor/PhabricatorAuditEditor.php b/src/applications/audit/editor/PhabricatorAuditEditor.php
index 9c2a5d7e96..c6fa129e41 100644
--- a/src/applications/audit/editor/PhabricatorAuditEditor.php
+++ b/src/applications/audit/editor/PhabricatorAuditEditor.php
@@ -1,870 +1,870 @@
<?php
final class PhabricatorAuditEditor
extends PhabricatorApplicationTransactionEditor {
const MAX_FILES_SHOWN_IN_EMAIL = 1000;
private $affectedFiles;
private $rawPatch;
private $auditorPHIDs = array();
private $didExpandInlineState = false;
private $oldAuditStatus = null;
public function setRawPatch($patch) {
$this->rawPatch = $patch;
return $this;
}
public function getRawPatch() {
return $this->rawPatch;
}
public function getEditorApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Audits');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_INLINESTATE;
$types[] = PhabricatorAuditTransaction::TYPE_COMMIT;
// TODO: These will get modernized eventually, but that can happen one
// at a time later on.
$types[] = PhabricatorAuditActionConstants::INLINE;
return $types;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_INLINESTATE:
$this->didExpandInlineState = true;
break;
}
}
$this->oldAuditStatus = $object->getAuditStatus();
return parent::expandTransactions($object, $xactions);
}
protected function transactionHasEffect(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditActionConstants::INLINE:
return $xaction->hasComment();
}
return parent::transactionHasEffect($object, $xaction);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditActionConstants::INLINE:
case PhabricatorAuditTransaction::TYPE_COMMIT:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditActionConstants::INLINE:
case PhabricatorAuditTransaction::TYPE_COMMIT:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditActionConstants::INLINE:
$comment = $xaction->getComment();
$comment->setAttribute('editing', false);
PhabricatorVersionedDraft::purgeDrafts(
$comment->getPHID(),
$this->getActingAsPHID());
return;
case PhabricatorAuditTransaction::TYPE_COMMIT:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditTransaction::TYPE_COMMIT:
return;
case PhabricatorAuditActionConstants::INLINE:
$reply = $xaction->getComment()->getReplyToComment();
if ($reply && !$reply->getHasReplies()) {
$reply->setHasReplies(1)->save();
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function applyBuiltinExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_INLINESTATE:
$table = new PhabricatorAuditTransactionComment();
$conn_w = $table->establishConnection('w');
foreach ($xaction->getNewValue() as $phid => $state) {
queryfx(
$conn_w,
'UPDATE %T SET fixedState = %s WHERE phid = %s',
$table->getTableName(),
$state,
$phid);
}
break;
}
return parent::applyBuiltinExternalTransaction($object, $xaction);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// Load auditors explicitly; we may not have them if the caller was a
// generic piece of infrastructure.
$commit = id(new DiffusionCommitQuery())
->setViewer($this->requireActor())
->withIDs(array($object->getID()))
->needAuditRequests(true)
->executeOne();
if (!$commit) {
throw new Exception(
pht('Failed to load commit during transaction finalization!'));
}
$object->attachAudits($commit->getAudits());
$actor_phid = $this->getActingAsPHID();
$actor_is_author = ($object->getAuthorPHID()) &&
($actor_phid == $object->getAuthorPHID());
$import_status_flag = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditTransaction::TYPE_COMMIT:
$import_status_flag = PhabricatorRepositoryCommit::IMPORTED_PUBLISH;
break;
}
}
$old_status = $this->oldAuditStatus;
$requests = $object->getAudits();
$object->updateAuditStatus($requests);
$new_status = $object->getAuditStatus();
$object->save();
if ($import_status_flag) {
$object->writeImportStatusFlag($import_status_flag);
}
// If the commit has changed state after this edit, add an informational
// transaction about the state change.
if ($old_status != $new_status) {
if ($object->isAuditStatusPartiallyAudited()) {
// This state isn't interesting enough to get a transaction. The
// best way we could lead the user forward is something like "This
// commit still requires additional audits." but that's redundant and
// probably not very useful.
} else {
$xaction = $object->getApplicationTransactionTemplate()
->setTransactionType(DiffusionCommitStateTransaction::TRANSACTIONTYPE)
->setOldValue($old_status)
->setNewValue($new_status);
$xaction = $this->populateTransaction($object, $xaction);
$xaction->save();
}
}
// Collect auditor PHIDs for building mail.
$this->auditorPHIDs = mpull($object->getAudits(), 'getAuditorPHID');
return $xactions;
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$auditors_type = DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE;
$xactions = parent::expandTransaction($object, $xaction);
switch ($xaction->getTransactionType()) {
case PhabricatorAuditTransaction::TYPE_COMMIT:
$phids = $this->getAuditRequestTransactionPHIDsFromCommitMessage(
$object);
if ($phids) {
$xactions[] = $object->getApplicationTransactionTemplate()
->setTransactionType($auditors_type)
->setNewValue(
array(
'+' => array_fuse($phids),
));
$this->addUnmentionablePHIDs($phids);
}
break;
default:
break;
}
if (!$this->didExpandInlineState) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$this->didExpandInlineState = true;
$query_template = id(new DiffusionDiffInlineCommentQuery())
->withCommitPHIDs(array($object->getPHID()));
$state_xaction = $this->newInlineStateTransaction(
$object,
$query_template);
if ($state_xaction) {
$xactions[] = $state_xaction;
}
break;
}
}
return $xactions;
}
private function getAuditRequestTransactionPHIDsFromCommitMessage(
PhabricatorRepositoryCommit $commit) {
$actor = $this->getActor();
$data = $commit->getCommitData();
$message = $data->getCommitMessage();
$result = DifferentialCommitMessageParser::newStandardParser($actor)
->setRaiseMissingFieldErrors(false)
->parseFields($message);
$field_key = DifferentialAuditorsCommitMessageField::FIELDKEY;
$phids = idx($result, $field_key, null);
if (!$phids) {
return array();
}
// If a commit lists its author as an auditor, just pretend it does not.
foreach ($phids as $key => $phid) {
if ($phid == $commit->getAuthorPHID()) {
unset($phids[$key]);
}
}
if (!$phids) {
return array();
}
return $phids;
}
protected function sortTransactions(array $xactions) {
$xactions = parent::sortTransactions($xactions);
$head = array();
$tail = array();
foreach ($xactions as $xaction) {
$type = $xaction->getTransactionType();
if ($type == PhabricatorAuditActionConstants::INLINE) {
$tail[] = $xaction;
} else {
$head[] = $xaction;
}
}
return array_values(array_merge($head, $tail));
}
protected function supportsSearch() {
return true;
}
protected function expandCustomRemarkupBlockTransactions(
PhabricatorLiskDAO $object,
array $xactions,
array $changes,
PhutilMarkupEngine $engine) {
$actor = $this->getActor();
$result = array();
// Some interactions (like "Fixes Txxx" interacting with Maniphest) have
// already been processed, so we're only re-parsing them here to avoid
// generating an extra redundant mention. Other interactions are being
// processed for the first time.
// We're only recognizing magic in the commit message itself, not in
// audit comments.
$is_commit = false;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditTransaction::TYPE_COMMIT:
$is_commit = true;
break;
}
}
if (!$is_commit) {
return $result;
}
$flat_blocks = mpull($changes, 'getNewValue');
$huge_block = implode("\n\n", $flat_blocks);
$phid_map = array();
$monograms = array();
$task_refs = id(new ManiphestCustomFieldStatusParser())
->parseCorpus($huge_block);
foreach ($task_refs as $match) {
foreach ($match['monograms'] as $monogram) {
$monograms[] = $monogram;
}
}
$rev_refs = id(new DifferentialCustomFieldDependsOnParser())
->parseCorpus($huge_block);
foreach ($rev_refs as $match) {
foreach ($match['monograms'] as $monogram) {
$monograms[] = $monogram;
}
}
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getActor())
->withNames($monograms)
->execute();
$phid_map[] = mpull($objects, 'getPHID', 'getPHID');
$reverts_refs = id(new DifferentialCustomFieldRevertsParser())
->parseCorpus($huge_block);
$reverts = array_mergev(ipull($reverts_refs, 'monograms'));
if ($reverts) {
$reverted_objects = DiffusionCommitRevisionQuery::loadRevertedObjects(
$actor,
$object,
$reverts,
$object->getRepository());
$reverted_phids = mpull($reverted_objects, 'getPHID', 'getPHID');
$reverts_edge = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
$result[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $reverts_edge)
->setNewValue(array('+' => $reverted_phids));
$phid_map[] = $reverted_phids;
}
// See T13463. Copy "related task" edges from the associated revision, if
// one exists.
$revision = DiffusionCommitRevisionQuery::loadRevisionForCommit(
$actor,
$object);
if ($revision) {
$task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$revision->getPHID(),
DifferentialRevisionHasTaskEdgeType::EDGECONST);
$task_phids = array_fuse($task_phids);
if ($task_phids) {
$related_edge = DiffusionCommitHasTaskEdgeType::EDGECONST;
$result[] = id(new PhabricatorAuditTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $related_edge)
->setNewValue(array('+' => $task_phids));
}
// Mark these objects as unmentionable, since the explicit relationship
// is stronger and any mentions are redundant.
$phid_map[] = $task_phids;
}
$phid_map = array_mergev($phid_map);
$this->addUnmentionablePHIDs($phid_map);
return $result;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
$reply_handler = new PhabricatorAuditReplyHandler();
$reply_handler->setMailReceiver($object);
return $reply_handler;
}
protected function getMailSubjectPrefix() {
return pht('[Diffusion]');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
// For backward compatibility, use this legacy thread ID.
return 'diffusion-audit-'.$object->getPHID();
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$identifier = $object->getCommitIdentifier();
$repository = $object->getRepository();
$summary = $object->getSummary();
$name = $repository->formatCommitName($identifier);
$subject = "{$name}: {$summary}";
$template = id(new PhabricatorMetaMTAMail())
->setSubject($subject);
$this->attachPatch(
$template,
$object);
return $template;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$this->requireAuditors($object);
$phids = array();
if ($object->getAuthorPHID()) {
$phids[] = $object->getAuthorPHID();
}
foreach ($object->getAudits() as $audit) {
if (!$audit->isResigned()) {
$phids[] = $audit->getAuditorPHID();
}
}
$phids[] = $this->getActingAsPHID();
return $phids;
}
protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) {
$this->requireAuditors($object);
$phids = array();
foreach ($object->getAudits() as $auditor) {
if ($auditor->isResigned()) {
$phids[] = $auditor->getAuditorPHID();
}
}
return $phids;
}
protected function getObjectLinkButtonLabelForMail(
PhabricatorLiskDAO $object) {
return pht('View Commit');
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$type_inline = PhabricatorAuditActionConstants::INLINE;
$type_push = PhabricatorAuditTransaction::TYPE_COMMIT;
$is_commit = false;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $type_inline) {
$inlines[] = $xaction;
}
if ($xaction->getTransactionType() == $type_push) {
$is_commit = true;
}
}
if ($inlines) {
$body->addTextSection(
pht('INLINE COMMENTS'),
$this->renderInlineCommentsForMail($object, $inlines));
}
if ($is_commit) {
$data = $object->getCommitData();
$body->addTextSection(pht('AFFECTED FILES'), $this->affectedFiles);
$this->inlinePatch(
$body,
$object);
}
$data = $object->getCommitData();
$user_phids = array();
$author_phid = $object->getAuthorPHID();
if ($author_phid) {
$user_phids[$author_phid][] = pht('Author');
}
$committer_phid = $data->getCommitDetail('committerPHID');
if ($committer_phid && ($committer_phid != $author_phid)) {
$user_phids[$committer_phid][] = pht('Committer');
}
foreach ($this->auditorPHIDs as $auditor_phid) {
$user_phids[$auditor_phid][] = pht('Auditor');
}
// TODO: It would be nice to show pusher here too, but that information
// is a little tricky to get at right now.
if ($user_phids) {
$handle_phids = array_keys($user_phids);
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->requireActor())
->withPHIDs($handle_phids)
->execute();
$user_info = array();
foreach ($user_phids as $phid => $roles) {
$user_info[] = pht(
'%s (%s)',
$handles[$phid]->getName(),
implode(', ', $roles));
}
$body->addTextSection(
pht('USERS'),
implode("\n", $user_info));
}
$monogram = $object->getRepository()->formatCommitName(
$object->getCommitIdentifier());
$body->addLinkSection(
pht('COMMIT'),
PhabricatorEnv::getProductionURI('/'.$monogram));
return $body;
}
private function attachPatch(
PhabricatorMetaMTAMail $template,
PhabricatorRepositoryCommit $commit) {
if (!$this->getRawPatch()) {
return;
}
$attach_key = 'metamta.diffusion.attach-patches';
$attach_patches = PhabricatorEnv::getEnvConfig($attach_key);
if (!$attach_patches) {
return;
}
$repository = $commit->getRepository();
$encoding = $repository->getDetail('encoding', 'UTF-8');
$raw_patch = $this->getRawPatch();
$commit_name = $repository->formatCommitName(
$commit->getCommitIdentifier());
$template->addAttachment(
new PhabricatorMailAttachment(
$raw_patch,
$commit_name.'.patch',
'text/x-patch; charset='.$encoding));
}
private function inlinePatch(
PhabricatorMetaMTAMailBody $body,
PhabricatorRepositoryCommit $commit) {
if (!$this->getRawPatch()) {
return;
}
$inline_key = 'metamta.diffusion.inline-patches';
$inline_patches = PhabricatorEnv::getEnvConfig($inline_key);
if (!$inline_patches) {
return;
}
$repository = $commit->getRepository();
$raw_patch = $this->getRawPatch();
$result = null;
$len = substr_count($raw_patch, "\n");
if ($len <= $inline_patches) {
// We send email as utf8, so we need to convert the text to utf8 if
// we can.
$encoding = $repository->getDetail('encoding', 'UTF-8');
if ($encoding) {
$raw_patch = phutil_utf8_convert($raw_patch, 'UTF-8', $encoding);
}
$result = phutil_utf8ize($raw_patch);
}
if ($result) {
$result = "PATCH\n\n{$result}\n";
}
$body->addRawSection($result);
}
private function renderInlineCommentsForMail(
PhabricatorLiskDAO $object,
array $inline_xactions) {
$inlines = mpull($inline_xactions, 'getComment');
$block = array();
$path_map = id(new DiffusionPathQuery())
->withPathIDs(mpull($inlines, 'getPathID'))
->execute();
$path_map = ipull($path_map, 'path', 'id');
foreach ($inlines as $inline) {
$path = idx($path_map, $inline->getPathID());
if ($path === null) {
continue;
}
$start = $inline->getLineNumber();
$len = $inline->getLineLength();
if ($len) {
$range = $start.'-'.($start + $len);
} else {
$range = $start;
}
$content = $inline->getContent();
$block[] = "{$path}:{$range} {$content}";
}
return implode("\n", $block);
}
public function getMailTagsMap() {
return array(
PhabricatorAuditTransaction::MAILTAG_COMMIT =>
pht('A commit is created.'),
PhabricatorAuditTransaction::MAILTAG_ACTION_CONCERN =>
pht('A commit has a concern raised against it.'),
PhabricatorAuditTransaction::MAILTAG_ACTION_ACCEPT =>
pht('A commit is accepted.'),
PhabricatorAuditTransaction::MAILTAG_ACTION_RESIGN =>
pht('A commit has an auditor resign.'),
PhabricatorAuditTransaction::MAILTAG_ACTION_CLOSE =>
pht('A commit is closed.'),
PhabricatorAuditTransaction::MAILTAG_ADD_AUDITORS =>
pht('A commit has auditors added.'),
PhabricatorAuditTransaction::MAILTAG_ADD_CCS =>
pht("A commit's subscribers change."),
PhabricatorAuditTransaction::MAILTAG_PROJECTS =>
pht("A commit's projects change."),
PhabricatorAuditTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a commit.'),
PhabricatorAuditTransaction::MAILTAG_OTHER =>
pht('Other commit activity not listed above occurs.'),
);
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuditTransaction::TYPE_COMMIT:
$repository = $object->getRepository();
$publisher = $repository->newPublisher();
if (!$publisher->shouldPublishCommit($object)) {
return false;
}
return true;
default:
break;
}
}
return parent::shouldApplyHeraldRules($object, $xactions);
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldCommitAdapter())
->setObject($object);
}
protected function didApplyHeraldRules(
PhabricatorLiskDAO $object,
HeraldAdapter $adapter,
HeraldTranscript $transcript) {
$limit = self::MAX_FILES_SHOWN_IN_EMAIL;
$files = $adapter->loadAffectedPaths();
sort($files);
if (count($files) > $limit) {
array_splice($files, $limit);
$files[] = pht(
'(This commit affected more than %d files. Only %d are shown here '.
'and additional ones are truncated.)',
$limit,
$limit);
}
$this->affectedFiles = implode("\n", $files);
return array();
}
private function isCommitMostlyImported(PhabricatorLiskDAO $object) {
$has_message = PhabricatorRepositoryCommit::IMPORTED_MESSAGE;
$has_changes = PhabricatorRepositoryCommit::IMPORTED_CHANGE;
// Don't publish feed stories or email about events which occur during
// import. In particular, this affects tasks being attached when they are
// closed by "Fixes Txxxx" in a commit message. See T5851.
$mask = ($has_message | $has_changes);
return $object->isPartiallyImported($mask);
}
private function shouldPublishRepositoryActivity(
PhabricatorLiskDAO $object,
array $xactions) {
// not every code path loads the repository so tread carefully
// TODO: They should, and then we should simplify this.
$repository = $object->getRepository($assert_attached = false);
if ($repository != PhabricatorLiskDAO::ATTACHABLE) {
$publisher = $repository->newPublisher();
if (!$publisher->shouldPublishCommit($object)) {
return false;
}
}
return $this->isCommitMostlyImported($object);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->shouldPublishRepositoryActivity($object, $xactions);
}
protected function shouldEnableMentions(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->shouldPublishRepositoryActivity($object, $xactions);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->shouldPublishRepositoryActivity($object, $xactions);
}
protected function getCustomWorkerState() {
return array(
'rawPatch' => $this->rawPatch,
'affectedFiles' => $this->affectedFiles,
'auditorPHIDs' => $this->auditorPHIDs,
);
}
protected function getCustomWorkerStateEncoding() {
return array(
'rawPatch' => self::STORAGE_ENCODING_BINARY,
);
}
protected function loadCustomWorkerState(array $state) {
$this->rawPatch = idx($state, 'rawPatch');
$this->affectedFiles = idx($state, 'affectedFiles');
$this->auditorPHIDs = idx($state, 'auditorPHIDs');
return $this;
}
protected function willPublish(PhabricatorLiskDAO $object, array $xactions) {
return id(new DiffusionCommitQuery())
->setViewer($this->requireActor())
->withIDs(array($object->getID()))
->needAuditRequests(true)
->needCommitData(true)
->executeOne();
}
private function requireAuditors(PhabricatorRepositoryCommit $commit) {
if ($commit->hasAttachedAudits()) {
return;
}
$with_auditors = id(new DiffusionCommitQuery())
->setViewer($this->getActor())
->needAuditRequests(true)
->withPHIDs(array($commit->getPHID()))
->executeOne();
if (!$with_auditors) {
throw new Exception(
pht(
'Failed to reload commit ("%s").',
$commit->getPHID()));
}
$commit->attachAudits($with_auditors->getAudits());
}
}
diff --git a/src/applications/audit/query/DiffusionInternalCommitSearchEngine.php b/src/applications/audit/query/DiffusionInternalCommitSearchEngine.php
index 45780140fb..ece9d1d48c 100644
--- a/src/applications/audit/query/DiffusionInternalCommitSearchEngine.php
+++ b/src/applications/audit/query/DiffusionInternalCommitSearchEngine.php
@@ -1,75 +1,75 @@
<?php
final class DiffusionInternalCommitSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Diffusion Raw Commits');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return new DiffusionCommitQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setDatasource(new DiffusionRepositoryFunctionDatasource())
->setDescription(pht('Find commits in particular repositories.')),
);
}
protected function getURI($path) {
return null;
}
protected function renderResultList(
array $commits,
PhabricatorSavedQuery $query,
array $handles) {
return null;
}
protected function getObjectWireFieldsForConduit(
$object,
array $field_extensions,
array $extension_data) {
$commit = $object;
$viewer = $this->requireViewer();
$repository = $commit->getRepository();
$identifier = $commit->getCommitIdentifier();
id(new DiffusionRepositoryClusterEngine())
->setViewer($viewer)
->setRepository($repository)
->synchronizeWorkingCopyBeforeRead();
$ref = id(new DiffusionLowLevelCommitQuery())
->setRepository($repository)
->withIdentifier($identifier)
->execute();
return array(
'ref' => $ref->newDictionary(),
);
}
}
diff --git a/src/applications/audit/query/PhabricatorCommitSearchEngine.php b/src/applications/audit/query/PhabricatorCommitSearchEngine.php
index 7251857c7f..a6a2ee071e 100644
--- a/src/applications/audit/query/PhabricatorCommitSearchEngine.php
+++ b/src/applications/audit/query/PhabricatorCommitSearchEngine.php
@@ -1,280 +1,280 @@
<?php
final class PhabricatorCommitSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Diffusion Commits');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return id(new DiffusionCommitQuery())
->needAuditRequests(true)
->needCommitData(true)
->needIdentities(true)
->needDrafts(true);
}
protected function newResultBuckets() {
return DiffusionCommitResultBucket::getAllResultBuckets();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['responsiblePHIDs']) {
$query->withResponsiblePHIDs($map['responsiblePHIDs']);
}
if ($map['auditorPHIDs']) {
$query->withAuditorPHIDs($map['auditorPHIDs']);
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['packagePHIDs']) {
$query->withPackagePHIDs($map['packagePHIDs']);
}
if ($map['unreachable'] !== null) {
$query->withUnreachable($map['unreachable']);
}
if ($map['permanent'] !== null) {
$query->withPermanent($map['permanent']);
}
if ($map['ancestorsOf']) {
$query->withAncestorsOf($map['ancestorsOf']);
}
if ($map['identifiers']) {
$query->withIdentifiers($map['identifiers']);
}
return $query;
}
protected function buildCustomSearchFields() {
$show_packages = PhabricatorApplication::isClassInstalled(
'PhabricatorPackagesApplication');
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Responsible Users'))
->setKey('responsiblePHIDs')
->setConduitKey('responsible')
->setAliases(array('responsible', 'responsibles', 'responsiblePHID'))
->setDatasource(new DifferentialResponsibleDatasource())
->setDescription(
pht(
'Find commits where given users, projects, or packages are '.
'responsible for the next steps in the audit workflow.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setConduitKey('authors')
->setAliases(array('author', 'authors', 'authorPHID'))
->setDescription(pht('Find commits authored by particular users.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Auditors'))
->setKey('auditorPHIDs')
->setConduitKey('auditors')
->setAliases(array('auditor', 'auditors', 'auditorPHID'))
->setDatasource(new DiffusionAuditorFunctionDatasource())
->setDescription(
pht(
'Find commits where given users, projects, or packages are '.
'auditors.')),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Audit Status'))
->setKey('statuses')
->setAliases(array('status'))
->setOptions(DiffusionCommitAuditStatus::newOptions())
->setDeprecatedOptions(
DiffusionCommitAuditStatus::newDeprecatedOptions())
->setDescription(pht('Find commits with given audit statuses.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setConduitKey('repositories')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setDatasource(new DiffusionRepositoryFunctionDatasource())
->setDescription(pht('Find commits in particular repositories.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Packages'))
->setKey('packagePHIDs')
->setConduitKey('packages')
->setAliases(array('package', 'packages', 'packagePHID'))
->setDatasource(new PhabricatorOwnersPackageDatasource())
->setIsHidden(!$show_packages)
->setDescription(
pht('Find commits which affect given packages.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Unreachable'))
->setKey('unreachable')
->setOptions(
pht('(Show All)'),
pht('Show Only Unreachable Commits'),
pht('Hide Unreachable Commits'))
->setDescription(
pht(
'Find or exclude unreachable commits which are not ancestors of '.
'any branch, tag, or ref.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Permanent'))
->setKey('permanent')
->setOptions(
pht('(Show All)'),
pht('Show Only Permanent Commits'),
pht('Hide Permanent Commits'))
->setDescription(
pht(
'Find or exclude permanent commits which are ancestors of '.
'any permanent branch, tag, or ref.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Ancestors Of'))
->setKey('ancestorsOf')
->setDescription(
pht(
'Find commits which are ancestors of a particular ref, '.
'like "master".')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Identifiers'))
->setKey('identifiers')
->setDescription(
pht(
'Find commits with particular identifiers (usually, hashes). '.
'Supports full or partial identifiers (like "abcd12340987..." or '.
'"abcd1234") and qualified or unqualified identifiers (like '.
'"rXabcd1234" or "abcd1234").')),
);
}
protected function getURI($path) {
return '/diffusion/commit/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['active'] = pht('Active Audits');
$names['authored'] = pht('Authored');
$names['audited'] = pht('Audited');
}
$names['all'] = pht('All Commits');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
$viewer_phid = $viewer->getPHID();
switch ($query_key) {
case 'all':
return $query;
case 'active':
$bucket_key = DiffusionCommitRequiredActionResultBucket::BUCKETKEY;
$open = DiffusionCommitAuditStatus::getOpenStatusConstants();
$query
->setParameter('responsiblePHIDs', array($viewer_phid))
->setParameter('statuses', $open)
->setParameter('bucket', $bucket_key)
->setParameter('unreachable', false);
return $query;
case 'authored':
$query
->setParameter('authorPHIDs', array($viewer_phid));
return $query;
case 'audited':
$query
->setParameter('auditorPHIDs', array($viewer_phid));
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $commits,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$viewer = $this->requireViewer();
$bucket = $this->getResultBucket($query);
$template = id(new DiffusionCommitGraphView())
->setViewer($viewer)
->setShowAuditors(true);
$views = array();
if ($bucket) {
$bucket->setViewer($viewer);
try {
$groups = $bucket->newResultGroups($query, $commits);
foreach ($groups as $group) {
// Don't show groups in Dashboard Panels
if ($group->getObjects() || !$this->isPanelContext()) {
$item_list = id(clone $template)
->setCommits($group->getObjects())
->newObjectItemListView();
$views[] = $item_list
->setHeader($group->getName())
->setNoDataString($group->getNoDataString());
}
}
} catch (Exception $ex) {
$this->addError($ex->getMessage());
}
}
if (!$views) {
$item_list = id(clone $template)
->setCommits($commits)
->newObjectItemListView();
$views[] = $item_list
->setNoDataString(pht('No commits found.'));
}
return id(new PhabricatorApplicationSearchResultView())
->setContent($views);
}
protected function getNewUserBody() {
$view = id(new PHUIBigInfoView())
->setIcon('fa-check-circle-o')
->setTitle(pht('Welcome to Audit'))
->setDescription(
pht('Post-commit code review and auditing. Audits you are assigned '.
'to will appear here.'));
return $view;
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthContactNumberEditEngine.php b/src/applications/auth/editor/PhabricatorAuthContactNumberEditEngine.php
index 5b1a059b2f..a4f1ab0cf2 100644
--- a/src/applications/auth/editor/PhabricatorAuthContactNumberEditEngine.php
+++ b/src/applications/auth/editor/PhabricatorAuthContactNumberEditEngine.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorAuthContactNumberEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'auth.contact';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Contact Numbers');
}
public function getSummaryHeader() {
return pht('Edit Contact Numbers');
}
public function getSummaryText() {
return pht('This engine is used to edit contact numbers.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return PhabricatorAuthContactNumber::initializeNewContactNumber($viewer);
}
protected function newObjectQuery() {
return new PhabricatorAuthContactNumberQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Contact Number');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Contact Number');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Contact Number');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create Contact Number');
}
protected function getObjectName() {
return pht('Contact Number');
}
protected function getEditorURI() {
return '/auth/contact/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/settings/panel/contact/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('contactNumber')
->setTransactionType(
PhabricatorAuthContactNumberNumberTransaction::TRANSACTIONTYPE)
->setLabel(pht('Contact Number'))
->setDescription(pht('The contact number.'))
->setValue($object->getContactNumber())
->setIsRequired(true),
);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthContactNumberEditor.php b/src/applications/auth/editor/PhabricatorAuthContactNumberEditor.php
index 9dfb569e89..d6c872743e 100644
--- a/src/applications/auth/editor/PhabricatorAuthContactNumberEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthContactNumberEditor.php
@@ -1,38 +1,38 @@
<?php
final class PhabricatorAuthContactNumberEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Contact Numbers');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this contact number.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
PhabricatorAuthContactNumberNumberTransaction::TRANSACTIONTYPE,
pht('Duplicate'),
pht('This contact number is already in use.'),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php b/src/applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php
index ab74350cc9..ecccfb6026 100644
--- a/src/applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php
+++ b/src/applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php
@@ -1,133 +1,133 @@
<?php
final class PhabricatorAuthFactorProviderEditEngine
extends PhabricatorEditEngine {
private $providerFactor;
const ENGINECONST = 'auth.factor.provider';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('MFA Providers');
}
public function getSummaryHeader() {
return pht('Edit MFA Providers');
}
public function getSummaryText() {
return pht('This engine is used to edit MFA providers.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function setProviderFactor(PhabricatorAuthFactor $factor) {
$this->providerFactor = $factor;
return $this;
}
public function getProviderFactor() {
return $this->providerFactor;
}
protected function newEditableObject() {
$factor = $this->getProviderFactor();
if ($factor) {
$provider = PhabricatorAuthFactorProvider::initializeNewProvider($factor);
} else {
$provider = new PhabricatorAuthFactorProvider();
}
return $provider;
}
protected function newObjectQuery() {
return new PhabricatorAuthFactorProviderQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create MFA Provider');
}
protected function getObjectCreateButtonText($object) {
return pht('Create MFA Provider');
}
protected function getObjectEditTitleText($object) {
return pht('Edit MFA Provider');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create MFA Provider');
}
protected function getObjectName() {
return pht('MFA Provider');
}
protected function getEditorURI() {
return '/auth/mfa/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/auth/mfa/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AuthManageProvidersCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$factor = $object->getFactor();
$factor_name = $factor->getFactorName();
$status_map = PhabricatorAuthFactorProviderStatus::getMap();
$fields = array(
id(new PhabricatorStaticEditField())
->setKey('displayType')
->setLabel(pht('Factor Type'))
->setDescription(pht('Type of the MFA provider.'))
->setValue($factor_name),
id(new PhabricatorTextEditField())
->setKey('name')
->setTransactionType(
PhabricatorAuthFactorProviderNameTransaction::TRANSACTIONTYPE)
->setLabel(pht('Name'))
->setDescription(pht('Display name for the MFA provider.'))
->setValue($object->getName())
->setPlaceholder($factor_name),
id(new PhabricatorSelectEditField())
->setKey('status')
->setTransactionType(
PhabricatorAuthFactorProviderStatusTransaction::TRANSACTIONTYPE)
->setLabel(pht('Status'))
->setDescription(pht('Status of the MFA provider.'))
->setValue($object->getStatus())
->setOptions($status_map),
);
$factor_fields = $factor->newEditEngineFields($this, $object);
foreach ($factor_fields as $field) {
$fields[] = $field;
}
return $fields;
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthFactorProviderEditor.php b/src/applications/auth/editor/PhabricatorAuthFactorProviderEditor.php
index 144f275391..7ee30a0ece 100644
--- a/src/applications/auth/editor/PhabricatorAuthFactorProviderEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthFactorProviderEditor.php
@@ -1,22 +1,22 @@
<?php
final class PhabricatorAuthFactorProviderEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('MFA Providers');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this MFA provider.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthMessageEditEngine.php b/src/applications/auth/editor/PhabricatorAuthMessageEditEngine.php
index 0a9aa32de4..3055201a8c 100644
--- a/src/applications/auth/editor/PhabricatorAuthMessageEditEngine.php
+++ b/src/applications/auth/editor/PhabricatorAuthMessageEditEngine.php
@@ -1,108 +1,108 @@
<?php
final class PhabricatorAuthMessageEditEngine
extends PhabricatorEditEngine {
private $messageType;
const ENGINECONST = 'auth.message';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Auth Messages');
}
public function getSummaryHeader() {
return pht('Edit Auth Messages');
}
public function getSummaryText() {
return pht('This engine is used to edit authentication messages.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function setMessageType(PhabricatorAuthMessageType $type) {
$this->messageType = $type;
return $this;
}
public function getMessageType() {
return $this->messageType;
}
protected function newEditableObject() {
$type = $this->getMessageType();
if ($type) {
$message = PhabricatorAuthMessage::initializeNewMessage($type);
} else {
$message = new PhabricatorAuthMessage();
}
return $message;
}
protected function newObjectQuery() {
return new PhabricatorAuthMessageQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Auth Message');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Auth Message');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Auth Message');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create Auth Message');
}
protected function getObjectName() {
return pht('Auth Message');
}
protected function getEditorURI() {
return '/auth/message/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/auth/message/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AuthManageProvidersCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorRemarkupEditField())
->setKey('messageText')
->setTransactionType(
PhabricatorAuthMessageTextTransaction::TRANSACTIONTYPE)
->setLabel(pht('Message Text'))
->setDescription(pht('Custom text for the message.'))
->setValue($object->getMessageText()),
);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthMessageEditor.php b/src/applications/auth/editor/PhabricatorAuthMessageEditor.php
index 56e8e716cd..24bc235680 100644
--- a/src/applications/auth/editor/PhabricatorAuthMessageEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthMessageEditor.php
@@ -1,22 +1,22 @@
<?php
final class PhabricatorAuthMessageEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Auth Messages');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this message.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php b/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php
index 0867d22b87..447808f6c9 100644
--- a/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php
@@ -1,33 +1,33 @@
<?php
final class PhabricatorAuthPasswordEditor
extends PhabricatorApplicationTransactionEditor {
private $oldHasher;
public function setOldHasher(PhabricatorPasswordHasher $old_hasher) {
$this->oldHasher = $old_hasher;
return $this;
}
public function getOldHasher() {
return $this->oldHasher;
}
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Passwords');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this password.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthProviderConfigEditor.php b/src/applications/auth/editor/PhabricatorAuthProviderConfigEditor.php
index 1e75edfbf0..4f66d36d04 100644
--- a/src/applications/auth/editor/PhabricatorAuthProviderConfigEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthProviderConfigEditor.php
@@ -1,149 +1,149 @@
<?php
final class PhabricatorAuthProviderConfigEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Auth Providers');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_LINK;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN;
$types[] = PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE:
if ($object->getIsEnabled() === null) {
return null;
} else {
return (int)$object->getIsEnabled();
}
case PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN:
return (int)$object->getShouldAllowLogin();
case PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION:
return (int)$object->getShouldAllowRegistration();
case PhabricatorAuthProviderConfigTransaction::TYPE_LINK:
return (int)$object->getShouldAllowLink();
case PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK:
return (int)$object->getShouldAllowUnlink();
case PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS:
return (int)$object->getShouldTrustEmails();
case PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN:
return (int)$object->getShouldAutoLogin();
case PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue(
PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
return $object->getProperty($key);
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE:
case PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN:
case PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION:
case PhabricatorAuthProviderConfigTransaction::TYPE_LINK:
case PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK:
case PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS:
case PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN:
case PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY:
return $xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$v = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
case PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE:
return $object->setIsEnabled($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN:
return $object->setShouldAllowLogin($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION:
return $object->setShouldAllowRegistration($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_LINK:
return $object->setShouldAllowLink($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK:
return $object->setShouldAllowUnlink($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS:
return $object->setShouldTrustEmails($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN:
return $object->setShouldAutoLogin($v);
case PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue(
PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
return $object->setProperty($key, $v);
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$type = $u->getTransactionType();
switch ($type) {
case PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE:
case PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN:
case PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION:
case PhabricatorAuthProviderConfigTransaction::TYPE_LINK:
case PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK:
case PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS:
case PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN:
// For these types, last transaction wins.
return $v;
}
return parent::mergeTransactions($u, $v);
}
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$errors = parent::validateAllTransactions($object, $xactions);
$locked_config_key = 'auth.lock-config';
$is_locked = PhabricatorEnv::getEnvConfig($locked_config_key);
if ($is_locked) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
null,
pht('Config Locked'),
pht('Authentication provider configuration is locked, and can not be '.
'changed without being unlocked.'),
null);
}
return $errors;
}
}
diff --git a/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php b/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
index 3f178c9855..b8114a257f 100644
--- a/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
+++ b/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
@@ -1,305 +1,305 @@
<?php
final class PhabricatorAuthSSHKeyEditor
extends PhabricatorApplicationTransactionEditor {
private $isAdministrativeEdit;
public function setIsAdministrativeEdit($is_administrative_edit) {
$this->isAdministrativeEdit = $is_administrative_edit;
return $this;
}
public function getIsAdministrativeEdit() {
return $this->isAdministrativeEdit;
}
public function getEditorApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function getEditorObjectsDescription() {
return pht('SSH Keys');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorAuthSSHKeyTransaction::TYPE_NAME;
$types[] = PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
$types[] = PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
return $object->getEntireKey();
case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
return !$object->getIsActive();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
return $xaction->getNewValue();
case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
return (bool)$xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$value = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
$object->setName($value);
return;
case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
$public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($value);
$type = $public_key->getType();
$body = $public_key->getBody();
$comment = $public_key->getComment();
$object->setKeyType($type);
$object->setKeyBody($body);
$object->setKeyComment($comment);
return;
case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
if ($value) {
$new = null;
} else {
$new = 1;
}
$object->setIsActive($new);
return;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$viewer = $this->requireActor();
switch ($type) {
case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('SSH key name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
case PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('SSH key material is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else {
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
try {
$public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($new);
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
continue;
}
// The database does not have a unique key on just the <keyBody>
// column because we allow multiple accounts to revoke the same
// key, so we can't rely on database constraints to prevent users
// from adding keys that are on the revocation list back to their
// accounts. Explicitly check for a revoked copy of the key.
$revoked_keys = id(new PhabricatorAuthSSHKeyQuery())
->setViewer($viewer)
->withObjectPHIDs(array($object->getObjectPHID()))
->withIsActive(0)
->withKeys(array($public_key))
->execute();
if ($revoked_keys) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Revoked'),
pht(
'This key has been revoked. Choose or generate a new, '.
'unique key.'),
$xaction);
continue;
}
}
}
break;
case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
foreach ($xactions as $xaction) {
if (!$xaction->getNewValue()) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('SSH keys can not be reactivated.'),
$xaction);
}
}
break;
}
return $errors;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
PhabricatorAuthSSHKeyTransaction::TYPE_KEY,
pht('Duplicate'),
pht(
'This public key is already associated with another user or device. '.
'Each key must unambiguously identify a single unique owner.'),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[SSH Key]');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
return 'ssh-key-'.$object->getPHID();
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// After making any change to an SSH key, drop the authfile cache so it
// is regenerated the next time anyone authenticates.
PhabricatorAuthSSHKeyQuery::deleteSSHKeyCache();
return $xactions;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return $object->getObject()->getSSHKeyNotifyPHIDs();
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorAuthSSHKeyReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
$mail = id(new PhabricatorMetaMTAMail())
->setSubject(pht('SSH Key %d: %s', $id, $name));
// The primary value of this mail is alerting users to account compromises,
// so force delivery. In particular, this mail should still be delivered
// even if "self mail" is disabled.
$mail->setForceDelivery(true);
return $mail;
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
if (!$this->getIsAdministrativeEdit()) {
$body->addTextSection(
pht('SECURITY WARNING'),
pht(
'If you do not recognize this change, it may indicate your account '.
'has been compromised.'));
}
$detail_uri = $object->getURI();
$detail_uri = PhabricatorEnv::getProductionURI($detail_uri);
$body->addLinkSection(pht('SSH KEY DETAIL'), $detail_uri);
return $body;
}
protected function getCustomWorkerState() {
return array(
'isAdministrativeEdit' => $this->isAdministrativeEdit,
);
}
protected function loadCustomWorkerState(array $state) {
$this->isAdministrativeEdit = idx($state, 'isAdministrativeEdit');
return $this;
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php b/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php
index 2819c84572..c7531e61b0 100644
--- a/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorAuthAuthFactorPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AFTR';
public function getTypeName() {
return pht('Auth Factor');
}
public function newObject() {
return new PhabricatorAuthFactorConfig();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
// TODO: Maybe we need this eventually?
throw new PhutilMethodNotImplementedException();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$factor = $objects[$phid];
$handle->setName($factor->getFactorName());
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php b/src/applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php
index f0f9f572e8..23d932cfb9 100644
--- a/src/applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorAuthAuthFactorProviderPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'FPRV';
public function getTypeName() {
return pht('MFA Provider');
}
public function newObject() {
return new PhabricatorAuthFactorProvider();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthFactorProviderQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$provider = $objects[$phid];
$handle->setURI($provider->getURI());
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php b/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php
index bf79ea8743..00b9cd9c6e 100644
--- a/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorAuthAuthProviderPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AUTH';
public function getTypeName() {
return pht('Auth Provider');
}
public function newObject() {
return new PhabricatorAuthProviderConfig();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthProviderConfigQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$provider = $objects[$phid]->getProvider();
if ($provider) {
$handle->setName($provider->getProviderName());
}
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthChallengePHIDType.php b/src/applications/auth/phid/PhabricatorAuthChallengePHIDType.php
index 2d2fea26b6..23b2e485c2 100644
--- a/src/applications/auth/phid/PhabricatorAuthChallengePHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthChallengePHIDType.php
@@ -1,32 +1,32 @@
<?php
final class PhabricatorAuthChallengePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CHAL';
public function getTypeName() {
return pht('Auth Challenge');
}
public function newObject() {
return new PhabricatorAuthChallenge();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return new PhabricatorAuthChallengeQuery();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
return;
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthContactNumberPHIDType.php b/src/applications/auth/phid/PhabricatorAuthContactNumberPHIDType.php
index 8a4953f4d3..e883aaa5a6 100644
--- a/src/applications/auth/phid/PhabricatorAuthContactNumberPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthContactNumberPHIDType.php
@@ -1,38 +1,38 @@
<?php
final class PhabricatorAuthContactNumberPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'CTNM';
public function getTypeName() {
return pht('Contact Number');
}
public function newObject() {
return new PhabricatorAuthContactNumber();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthContactNumberQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$contact_number = $objects[$phid];
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php b/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php
index b633e10eab..e22793990d 100644
--- a/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php
@@ -1,35 +1,35 @@
<?php
final class PhabricatorAuthInvitePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AINV';
public function getTypeName() {
return pht('Auth Invite');
}
public function newObject() {
return new PhabricatorAuthInvite();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
throw new PhutilMethodNotImplementedException();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$invite = $objects[$phid];
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthMessagePHIDType.php b/src/applications/auth/phid/PhabricatorAuthMessagePHIDType.php
index 005e363b08..c1cd101060 100644
--- a/src/applications/auth/phid/PhabricatorAuthMessagePHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthMessagePHIDType.php
@@ -1,38 +1,38 @@
<?php
final class PhabricatorAuthMessagePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AMSG';
public function getTypeName() {
return pht('Auth Message');
}
public function newObject() {
return new PhabricatorAuthMessage();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthMessageQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$message = $objects[$phid];
$handle->setURI($message->getURI());
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php b/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php
index 8433df8824..b0256a1bf6 100644
--- a/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php
@@ -1,36 +1,36 @@
<?php
final class PhabricatorAuthPasswordPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'APAS';
public function getTypeName() {
return pht('Auth Password');
}
public function newObject() {
return new PhabricatorAuthPassword();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthPasswordQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$password = $objects[$phid];
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php b/src/applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php
index b09bdb8b80..e18475ceb9 100644
--- a/src/applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhabricatorAuthSSHKeyPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'AKEY';
public function getTypeName() {
return pht('Public SSH Key');
}
public function newObject() {
return new PhabricatorAuthSSHKey();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthSSHKeyQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$key = $objects[$phid];
$handle->setName(pht('SSH Key %d', $key->getID()));
if (!$key->getIsActive()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/auth/phid/PhabricatorAuthSessionPHIDType.php b/src/applications/auth/phid/PhabricatorAuthSessionPHIDType.php
index e031c4ae88..ae67f09433 100644
--- a/src/applications/auth/phid/PhabricatorAuthSessionPHIDType.php
+++ b/src/applications/auth/phid/PhabricatorAuthSessionPHIDType.php
@@ -1,34 +1,34 @@
<?php
final class PhabricatorAuthSessionPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'SSSN';
public function getTypeName() {
return pht('Session');
}
public function newObject() {
return new PhabricatorAuthSession();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthSessionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
return;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthChallengeQuery.php b/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
index c6abead11f..9b0b776d0d 100644
--- a/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthChallengeQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhabricatorAuthChallengeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $userPHIDs;
private $factorPHIDs;
private $challengeTTLMin;
private $challengeTTLMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withFactorPHIDs(array $factor_phids) {
$this->factorPHIDs = $factor_phids;
return $this;
}
public function withChallengeTTLBetween($challenge_min, $challenge_max) {
$this->challengeTTLMin = $challenge_min;
$this->challengeTTLMax = $challenge_max;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthChallenge();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->factorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'factorPHID IN (%Ls)',
$this->factorPHIDs);
}
if ($this->challengeTTLMin !== null) {
$where[] = qsprintf(
$conn,
'challengeTTL >= %d',
$this->challengeTTLMin);
}
if ($this->challengeTTLMax !== null) {
$where[] = qsprintf(
$conn,
'challengeTTL <= %d',
$this->challengeTTLMax);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php b/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
index ba507c757b..a3b781485f 100644
--- a/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthContactNumberQuery.php
@@ -1,99 +1,99 @@
<?php
final class PhabricatorAuthContactNumberQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $objectPHIDs;
private $statuses;
private $uniqueKeys;
private $isPrimary;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withUniqueKeys(array $unique_keys) {
$this->uniqueKeys = $unique_keys;
return $this;
}
public function withIsPrimary($is_primary) {
$this->isPrimary = $is_primary;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthContactNumber();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
if ($this->uniqueKeys !== null) {
$where[] = qsprintf(
$conn,
'uniqueKey IN (%Ls)',
$this->uniqueKeys);
}
if ($this->isPrimary !== null) {
$where[] = qsprintf(
$conn,
'isPrimary = %d',
(int)$this->isPrimary);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php b/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
index dd73d0b081..52b907e62f 100644
--- a/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthFactorConfigQuery.php
@@ -1,127 +1,127 @@
<?php
final class PhabricatorAuthFactorConfigQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $userPHIDs;
private $factorProviderPHIDs;
private $factorProviderStatuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withFactorProviderPHIDs(array $provider_phids) {
$this->factorProviderPHIDs = $provider_phids;
return $this;
}
public function withFactorProviderStatuses(array $statuses) {
$this->factorProviderStatuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthFactorConfig();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'config.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'config.phid IN (%Ls)',
$this->phids);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'config.userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->factorProviderPHIDs !== null) {
$where[] = qsprintf(
$conn,
'config.factorProviderPHID IN (%Ls)',
$this->factorProviderPHIDs);
}
if ($this->factorProviderStatuses !== null) {
$where[] = qsprintf(
$conn,
'provider.status IN (%Ls)',
$this->factorProviderStatuses);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->factorProviderStatuses !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %R provider ON config.factorProviderPHID = provider.phid',
new PhabricatorAuthFactorProvider());
}
return $joins;
}
protected function willFilterPage(array $configs) {
$provider_phids = mpull($configs, 'getFactorProviderPHID');
$providers = id(new PhabricatorAuthFactorProviderQuery())
->setViewer($this->getViewer())
->withPHIDs($provider_phids)
->execute();
$providers = mpull($providers, null, 'getPHID');
foreach ($configs as $key => $config) {
$provider = idx($providers, $config->getFactorProviderPHID());
if (!$provider) {
unset($configs[$key]);
$this->didRejectResult($config);
continue;
}
$config->attachFactorProvider($provider);
}
return $configs;
}
protected function getPrimaryTableAlias() {
return 'config';
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php b/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
index 7083545e3e..362f6be235 100644
--- a/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthFactorProviderQuery.php
@@ -1,90 +1,90 @@
<?php
final class PhabricatorAuthFactorProviderQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $providerFactorKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProviderFactorKeys(array $keys) {
$this->providerFactorKeys = $keys;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthFactorProvider();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
if ($this->providerFactorKeys !== null) {
$where[] = qsprintf(
$conn,
'providerFactorKey IN (%Ls)',
$this->providerFactorKeys);
}
return $where;
}
protected function willFilterPage(array $providers) {
$map = PhabricatorAuthFactor::getAllFactors();
foreach ($providers as $key => $provider) {
$factor_key = $provider->getProviderFactorKey();
$factor = idx($map, $factor_key);
if (!$factor) {
unset($providers[$key]);
continue;
}
$provider->attachFactor($factor);
}
return $providers;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthInviteSearchEngine.php b/src/applications/auth/query/PhabricatorAuthInviteSearchEngine.php
index e439dd9fb8..8ed2a31e6c 100644
--- a/src/applications/auth/query/PhabricatorAuthInviteSearchEngine.php
+++ b/src/applications/auth/query/PhabricatorAuthInviteSearchEngine.php
@@ -1,114 +1,114 @@
<?php
final class PhabricatorAuthInviteSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Auth Email Invites');
}
public function getApplicationClassName() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorAuthInviteQuery());
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {}
protected function getURI($path) {
return '/people/invite/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $invites,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($invites as $invite) {
$phids[$invite->getAuthorPHID()] = true;
if ($invite->getAcceptedByPHID()) {
$phids[$invite->getAcceptedByPHID()] = true;
}
}
return array_keys($phids);
}
protected function renderResultList(
array $invites,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($invites, 'PhabricatorAuthInvite');
$viewer = $this->requireViewer();
$rows = array();
foreach ($invites as $invite) {
$rows[] = array(
$invite->getEmailAddress(),
$handles[$invite->getAuthorPHID()]->renderLink(),
($invite->getAcceptedByPHID()
? $handles[$invite->getAcceptedByPHID()]->renderLink()
: null),
phabricator_datetime($invite->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
pht('Email Address'),
pht('Sent By'),
pht('Accepted By'),
pht('Invited'),
))
->setColumnClasses(
array(
'',
'',
'wide',
'right',
));
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
return $result;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthMessageQuery.php b/src/applications/auth/query/PhabricatorAuthMessageQuery.php
index 7158d03a00..c28d561297 100644
--- a/src/applications/auth/query/PhabricatorAuthMessageQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthMessageQuery.php
@@ -1,79 +1,79 @@
<?php
final class PhabricatorAuthMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $messageKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMessageKeys(array $keys) {
$this->messageKeys = $keys;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthMessage();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->messageKeys !== null) {
$where[] = qsprintf(
$conn,
'messageKey IN (%Ls)',
$this->messageKeys);
}
return $where;
}
protected function willFilterPage(array $messages) {
$message_types = PhabricatorAuthMessageType::getAllMessageTypes();
foreach ($messages as $key => $message) {
$message_key = $message->getMessageKey();
$message_type = idx($message_types, $message_key);
if (!$message_type) {
unset($messages[$key]);
$this->didRejectResult($message);
continue;
}
$message->attachMessageType($message_type);
}
return $messages;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthPasswordQuery.php b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
index a77fd54b13..0e9e70e175 100644
--- a/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
@@ -1,110 +1,110 @@
<?php
final class PhabricatorAuthPasswordQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $objectPHIDs;
private $passwordTypes;
private $isRevoked;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withPasswordTypes(array $types) {
$this->passwordTypes = $types;
return $this;
}
public function withIsRevoked($is_revoked) {
$this->isRevoked = $is_revoked;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthPassword();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->passwordTypes !== null) {
$where[] = qsprintf(
$conn,
'passwordType IN (%Ls)',
$this->passwordTypes);
}
if ($this->isRevoked !== null) {
$where[] = qsprintf(
$conn,
'isRevoked = %d',
(int)$this->isRevoked);
}
return $where;
}
protected function willFilterPage(array $passwords) {
$object_phids = mpull($passwords, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($passwords as $key => $password) {
$object = idx($objects, $password->getObjectPHID());
if (!$object) {
unset($passwords[$key]);
$this->didRejectResult($password);
continue;
}
$password->attachObject($object);
}
return $passwords;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
index 30e5dad113..d437d08fd5 100644
--- a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorAuthProviderConfigQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $providerClasses;
private $isEnabled;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withProviderClasses(array $classes) {
$this->providerClasses = $classes;
return $this;
}
public function withIsEnabled($is_enabled) {
$this->isEnabled = $is_enabled;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthProviderConfig();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->providerClasses !== null) {
$where[] = qsprintf(
$conn,
'providerClass IN (%Ls)',
$this->providerClasses);
}
if ($this->isEnabled !== null) {
$where[] = qsprintf(
$conn,
'isEnabled = %d',
(int)$this->isEnabled);
}
return $where;
}
protected function willFilterPage(array $configs) {
foreach ($configs as $key => $config) {
$provider = $config->getProvider();
if (!$provider) {
unset($configs[$key]);
continue;
}
}
return $configs;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php b/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
index 7d4aac4a01..e0970f9b51 100644
--- a/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthSSHKeyQuery.php
@@ -1,134 +1,134 @@
<?php
final class PhabricatorAuthSSHKeyQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const AUTHSTRUCT_CACHEKEY = 'ssh.authstruct';
private $ids;
private $phids;
private $objectPHIDs;
private $keys;
private $isActive;
public static function deleteSSHKeyCache() {
$cache = PhabricatorCaches::getMutableCache();
$authfile_key = self::AUTHSTRUCT_CACHEKEY;
$cache->deleteKey($authfile_key);
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withKeys(array $keys) {
assert_instances_of($keys, 'PhabricatorAuthSSHPublicKey');
$this->keys = $keys;
return $this;
}
public function withIsActive($active) {
$this->isActive = $active;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthSSHKey();
}
protected function willFilterPage(array $keys) {
$object_phids = mpull($keys, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($keys as $key => $ssh_key) {
$object = idx($objects, $ssh_key->getObjectPHID());
// We must have an object, and that object must be a valid object for
// SSH keys.
if (!$object || !($object instanceof PhabricatorSSHPublicKeyInterface)) {
$this->didRejectResult($ssh_key);
unset($keys[$key]);
continue;
}
$ssh_key->attachObject($object);
}
return $keys;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->keys !== null) {
$sql = array();
foreach ($this->keys as $key) {
$sql[] = qsprintf(
$conn,
'(keyType = %s AND keyIndex = %s)',
$key->getType(),
$key->getHash());
}
$where[] = qsprintf($conn, '%LO', $sql);
}
if ($this->isActive !== null) {
if ($this->isActive) {
$where[] = qsprintf(
$conn,
'isActive = %d',
1);
} else {
$where[] = qsprintf(
$conn,
'isActive IS NULL');
}
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php b/src/applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php
index 0575b40b9c..133389dc8e 100644
--- a/src/applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php
+++ b/src/applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php
@@ -1,105 +1,105 @@
<?php
final class PhabricatorAuthSSHKeySearchEngine
extends PhabricatorApplicationSearchEngine {
private $sshKeyObject;
public function setSSHKeyObject(PhabricatorSSHPublicKeyInterface $object) {
$this->sshKeyObject = $object;
return $this;
}
public function getSSHKeyObject() {
return $this->sshKeyObject;
}
public function canUseInPanelContext() {
return false;
}
public function getResultTypeDescription() {
return pht('SSH Keys');
}
public function getApplicationClassName() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
public function newQuery() {
$object = $this->getSSHKeyObject();
$object_phid = $object->getPHID();
return id(new PhabricatorAuthSSHKeyQuery())
->withObjectPHIDs(array($object_phid));
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getURI($path) {
$object = $this->getSSHKeyObject();
$object_phid = $object->getPHID();
return "/auth/sshkey/for/{$object_phid}/{$path}";
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Keys'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $keys,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($keys, 'PhabricatorAuthSSHKey');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($keys as $key) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('SSH Key %d', $key->getID()))
->setHeader($key->getName())
->setHref($key->getURI());
if (!$key->getIsActive()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No matching SSH keys.'));
return $result;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthSessionQuery.php b/src/applications/auth/query/PhabricatorAuthSessionQuery.php
index 4bc7eba73f..78974c7670 100644
--- a/src/applications/auth/query/PhabricatorAuthSessionQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthSessionQuery.php
@@ -1,113 +1,113 @@
<?php
final class PhabricatorAuthSessionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $identityPHIDs;
private $sessionKeys;
private $sessionTypes;
public function withIdentityPHIDs(array $identity_phids) {
$this->identityPHIDs = $identity_phids;
return $this;
}
public function withSessionKeys(array $keys) {
$this->sessionKeys = $keys;
return $this;
}
public function withSessionTypes(array $types) {
$this->sessionTypes = $types;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthSession();
}
protected function willFilterPage(array $sessions) {
$identity_phids = mpull($sessions, 'getUserPHID');
$identity_objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($identity_phids)
->execute();
$identity_objects = mpull($identity_objects, null, 'getPHID');
foreach ($sessions as $key => $session) {
$identity_object = idx($identity_objects, $session->getUserPHID());
if (!$identity_object) {
unset($sessions[$key]);
} else {
$session->attachIdentityObject($identity_object);
}
}
return $sessions;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->identityPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->identityPHIDs);
}
if ($this->sessionKeys !== null) {
$hashes = array();
foreach ($this->sessionKeys as $session_key) {
$hashes[] = PhabricatorAuthSession::newSessionDigest(
new PhutilOpaqueEnvelope($session_key));
}
$where[] = qsprintf(
$conn,
'sessionKey IN (%Ls)',
$hashes);
}
if ($this->sessionTypes !== null) {
$where[] = qsprintf(
$conn,
'type IN (%Ls)',
$this->sessionTypes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php b/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
index c5cb39096c..90b4741307 100644
--- a/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
+++ b/src/applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php
@@ -1,106 +1,106 @@
<?php
final class PhabricatorAuthTemporaryTokenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $tokenResources;
private $tokenTypes;
private $userPHIDs;
private $expired;
private $tokenCodes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withTokenResources(array $resources) {
$this->tokenResources = $resources;
return $this;
}
public function withTokenTypes(array $types) {
$this->tokenTypes = $types;
return $this;
}
public function withExpired($expired) {
$this->expired = $expired;
return $this;
}
public function withTokenCodes(array $codes) {
$this->tokenCodes = $codes;
return $this;
}
public function withUserPHIDs(array $phids) {
$this->userPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthTemporaryToken();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->tokenResources !== null) {
$where[] = qsprintf(
$conn,
'tokenResource IN (%Ls)',
$this->tokenResources);
}
if ($this->tokenTypes !== null) {
$where[] = qsprintf(
$conn,
'tokenType IN (%Ls)',
$this->tokenTypes);
}
if ($this->expired !== null) {
if ($this->expired) {
$where[] = qsprintf(
$conn,
'tokenExpires <= %d',
time());
} else {
$where[] = qsprintf(
$conn,
'tokenExpires > %d',
time());
}
}
if ($this->tokenCodes !== null) {
$where[] = qsprintf(
$conn,
'tokenCode IN (%Ls)',
$this->tokenCodes);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorAuthApplication';
+ return PhabricatorAuthApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php b/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
index b5c5b6eaa2..716fad59ba 100644
--- a/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
+++ b/src/applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php
@@ -1,90 +1,90 @@
<?php
final class PhabricatorExternalAccountIdentifierQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $providerConfigPHIDs;
private $externalAccountPHIDs;
private $rawIdentifiers;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProviderConfigPHIDs(array $phids) {
$this->providerConfigPHIDs = $phids;
return $this;
}
public function withExternalAccountPHIDs(array $phids) {
$this->externalAccountPHIDs = $phids;
return $this;
}
public function withRawIdentifiers(array $identifiers) {
$this->rawIdentifiers = $identifiers;
return $this;
}
public function newResultObject() {
return new PhabricatorExternalAccountIdentifier();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->providerConfigPHIDs !== null) {
$where[] = qsprintf(
$conn,
'providerConfigPHID IN (%Ls)',
$this->providerConfigPHIDs);
}
if ($this->externalAccountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'externalAccountPHID IN (%Ls)',
$this->externalAccountPHIDs);
}
if ($this->rawIdentifiers !== null) {
$hashes = array();
foreach ($this->rawIdentifiers as $raw_identifier) {
$hashes[] = PhabricatorHash::digestForIndex($raw_identifier);
}
$where[] = qsprintf(
$conn,
'identifierHash IN (%Ls)',
$hashes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
}
diff --git a/src/applications/auth/query/PhabricatorExternalAccountQuery.php b/src/applications/auth/query/PhabricatorExternalAccountQuery.php
index f44821d7a9..b2c61a1b91 100644
--- a/src/applications/auth/query/PhabricatorExternalAccountQuery.php
+++ b/src/applications/auth/query/PhabricatorExternalAccountQuery.php
@@ -1,247 +1,247 @@
<?php
/**
* NOTE: When loading ExternalAccounts for use in an authentication context
* (that is, you're going to act as the account or link identities or anything
* like that) you should require CAN_EDIT capability even if you aren't actually
* editing the ExternalAccount.
*
* ExternalAccounts have a permissive CAN_VIEW policy (like users) because they
* interact directly with objects and can leave comments, sign documents, etc.
* However, CAN_EDIT is restricted to users who own the accounts.
*/
final class PhabricatorExternalAccountQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $userPHIDs;
private $needImages;
private $accountSecrets;
private $providerConfigPHIDs;
private $needAccountIdentifiers;
private $rawAccountIdentifiers;
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withAccountSecrets(array $secrets) {
$this->accountSecrets = $secrets;
return $this;
}
public function needImages($need) {
$this->needImages = $need;
return $this;
}
public function needAccountIdentifiers($need) {
$this->needAccountIdentifiers = $need;
return $this;
}
public function withProviderConfigPHIDs(array $phids) {
$this->providerConfigPHIDs = $phids;
return $this;
}
public function withRawAccountIdentifiers(array $identifiers) {
$this->rawAccountIdentifiers = $identifiers;
return $this;
}
public function newResultObject() {
return new PhabricatorExternalAccount();
}
protected function willFilterPage(array $accounts) {
$viewer = $this->getViewer();
$configs = id(new PhabricatorAuthProviderConfigQuery())
->setViewer($viewer)
->withPHIDs(mpull($accounts, 'getProviderConfigPHID'))
->execute();
$configs = mpull($configs, null, 'getPHID');
foreach ($accounts as $key => $account) {
$config_phid = $account->getProviderConfigPHID();
$config = idx($configs, $config_phid);
if (!$config) {
unset($accounts[$key]);
continue;
}
$account->attachProviderConfig($config);
}
if ($this->needImages) {
$file_phids = mpull($accounts, 'getProfileImagePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
// NOTE: We use the omnipotent viewer here because these files are
// usually created during registration and can't be associated with
// the correct policies, since the relevant user account does not exist
// yet. In effect, if you can see an ExternalAccount, you can see its
// profile image.
$files = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
$default_file = null;
foreach ($accounts as $account) {
$image_phid = $account->getProfileImagePHID();
if ($image_phid && isset($files[$image_phid])) {
$account->attachProfileImageFile($files[$image_phid]);
} else {
if ($default_file === null) {
$default_file = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'profile.png');
}
$account->attachProfileImageFile($default_file);
}
}
}
if ($this->needAccountIdentifiers) {
$account_phids = mpull($accounts, 'getPHID');
$identifiers = id(new PhabricatorExternalAccountIdentifierQuery())
->setViewer($viewer)
->setParentQuery($this)
->withExternalAccountPHIDs($account_phids)
->execute();
$identifiers = mgroup($identifiers, 'getExternalAccountPHID');
foreach ($accounts as $account) {
$account_phid = $account->getPHID();
$account_identifiers = idx($identifiers, $account_phid, array());
$account->attachAccountIdentifiers($account_identifiers);
}
}
return $accounts;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'account.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'account.phid IN (%Ls)',
$this->phids);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'account.userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->accountSecrets !== null) {
$where[] = qsprintf(
$conn,
'account.accountSecret IN (%Ls)',
$this->accountSecrets);
}
if ($this->providerConfigPHIDs !== null) {
$where[] = qsprintf(
$conn,
'account.providerConfigPHID IN (%Ls)',
$this->providerConfigPHIDs);
// If we have a list of ProviderConfig PHIDs and are joining the
// identifiers table, also include the list as an additional constraint
// on the identifiers table.
// This does not change the query results (an Account and its
// Identifiers always have the same ProviderConfig PHID) but it allows
// us to use keys on the Identifier table more efficiently.
if ($this->shouldJoinIdentifiersTable()) {
$where[] = qsprintf(
$conn,
'identifier.providerConfigPHID IN (%Ls)',
$this->providerConfigPHIDs);
}
}
if ($this->rawAccountIdentifiers !== null) {
$hashes = array();
foreach ($this->rawAccountIdentifiers as $raw_identifier) {
$hashes[] = PhabricatorHash::digestForIndex($raw_identifier);
}
$where[] = qsprintf(
$conn,
'identifier.identifierHash IN (%Ls)',
$hashes);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinIdentifiersTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %R identifier ON account.phid = identifier.externalAccountPHID',
new PhabricatorExternalAccountIdentifier());
}
return $joins;
}
protected function shouldJoinIdentifiersTable() {
return ($this->rawAccountIdentifiers !== null);
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinIdentifiersTable()) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
protected function getPrimaryTableAlias() {
return 'account';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
}
diff --git a/src/applications/badges/editor/PhabricatorBadgesEditEngine.php b/src/applications/badges/editor/PhabricatorBadgesEditEngine.php
index 721184852c..5d95254bbd 100644
--- a/src/applications/badges/editor/PhabricatorBadgesEditEngine.php
+++ b/src/applications/badges/editor/PhabricatorBadgesEditEngine.php
@@ -1,147 +1,147 @@
<?php
final class PhabricatorBadgesEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'badges.badge';
public function getEngineName() {
return pht('Badges');
}
public function getEngineApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Badges Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Badges.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return PhabricatorBadgesBadge::initializeNewBadge($this->getViewer());
}
protected function newObjectQuery() {
return new PhabricatorBadgesQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Badge');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Badge: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Badge');
}
protected function getObjectName() {
return pht('Badge');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getCommentViewHeaderText($object) {
return pht('Render Honors');
}
protected function getCommentViewButtonText($object) {
return pht('Salute');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorBadgesCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Badge name.'))
->setConduitTypeDescription(pht('New badge name.'))
->setTransactionType(
PhabricatorBadgesBadgeNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName())
->setIsRequired(true),
id(new PhabricatorTextEditField())
->setKey('flavor')
->setLabel(pht('Flavor Text'))
->setDescription(pht('Short description of the badge.'))
->setConduitTypeDescription(pht('New badge flavor.'))
->setValue($object->getFlavor())
->setTransactionType(
PhabricatorBadgesBadgeFlavorTransaction::TRANSACTIONTYPE),
id(new PhabricatorIconSetEditField())
->setKey('icon')
->setLabel(pht('Icon'))
->setIconSet(new PhabricatorBadgesIconSet())
->setTransactionType(
PhabricatorBadgesBadgeIconTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Change the badge icon.'))
->setConduitTypeDescription(pht('New badge icon.'))
->setValue($object->getIcon()),
id(new PhabricatorSelectEditField())
->setKey('quality')
->setLabel(pht('Quality'))
->setDescription(pht('Color and rarity of the badge.'))
->setConduitTypeDescription(pht('New badge quality.'))
->setValue($object->getQuality())
->setTransactionType(
PhabricatorBadgesBadgeQualityTransaction::TRANSACTIONTYPE)
->setOptions(PhabricatorBadgesQuality::getDropdownQualityMap()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Badge long description.'))
->setConduitTypeDescription(pht('New badge description.'))
->setTransactionType(
PhabricatorBadgesBadgeDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorUsersEditField())
->setKey('award')
->setIsFormField(false)
->setDescription(pht('New badge award recipients.'))
->setConduitTypeDescription(pht('New badge award recipients.'))
->setTransactionType(
PhabricatorBadgesBadgeAwardTransaction::TRANSACTIONTYPE)
->setLabel(pht('Award Recipients')),
id(new PhabricatorUsersEditField())
->setKey('revoke')
->setIsFormField(false)
->setDescription(pht('Revoke badge award recipients.'))
->setConduitTypeDescription(pht('Revoke badge award recipients.'))
->setTransactionType(
PhabricatorBadgesBadgeRevokeTransaction::TRANSACTIONTYPE)
->setLabel(pht('Revoke Recipients')),
);
}
}
diff --git a/src/applications/badges/editor/PhabricatorBadgesEditor.php b/src/applications/badges/editor/PhabricatorBadgesEditor.php
index 785d8c989b..66b07390b5 100644
--- a/src/applications/badges/editor/PhabricatorBadgesEditor.php
+++ b/src/applications/badges/editor/PhabricatorBadgesEditor.php
@@ -1,160 +1,160 @@
<?php
final class PhabricatorBadgesEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Badges');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this badge.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
PhabricatorBadgesTransaction::MAILTAG_DETAILS =>
pht('Someone changes the badge\'s details.'),
PhabricatorBadgesTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a badge.'),
PhabricatorBadgesTransaction::MAILTAG_OTHER =>
pht('Other badge activity not listed above occurs.'),
);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$actor = $this->getActor();
$actor_phid = $actor->getPHID();
$results = parent::expandTransactions($object, $xactions);
// Automatically subscribe the author when they create a badge.
if ($this->getIsNewObject()) {
if ($actor_phid) {
$results[] = id(new PhabricatorBadgesTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(
array(
'+' => array($actor_phid => $actor_phid),
));
}
}
return $results;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorBadgesReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
$id = $object->getID();
$subject = pht('Badge %d: %s', $id, $name);
return id(new PhabricatorMetaMTAMail())
->setSubject($subject);
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getCreatorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('BADGE DETAIL'),
PhabricatorEnv::getProductionURI('/badges/view/'.$object->getID().'/'));
return $body;
}
protected function getMailSubjectPrefix() {
return pht('[Badge]');
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$badge_phid = $object->getPHID();
$user_phids = array();
$clear_everything = false;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorBadgesBadgeAwardTransaction::TRANSACTIONTYPE:
case PhabricatorBadgesBadgeRevokeTransaction::TRANSACTIONTYPE:
foreach ($xaction->getNewValue() as $user_phid) {
$user_phids[] = $user_phid;
}
break;
default:
$clear_everything = true;
break;
}
}
if ($clear_everything) {
$awards = id(new PhabricatorBadgesAwardQuery())
->setViewer($this->getActor())
->withBadgePHIDs(array($badge_phid))
->execute();
foreach ($awards as $award) {
$user_phids[] = $award->getRecipientPHID();
}
}
if ($user_phids) {
PhabricatorUserCache::clearCaches(
PhabricatorUserBadgesCacheType::KEY_BADGES,
$user_phids);
}
return $xactions;
}
}
diff --git a/src/applications/badges/phid/PhabricatorBadgesPHIDType.php b/src/applications/badges/phid/PhabricatorBadgesPHIDType.php
index 0adea047f9..072d62f529 100644
--- a/src/applications/badges/phid/PhabricatorBadgesPHIDType.php
+++ b/src/applications/badges/phid/PhabricatorBadgesPHIDType.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorBadgesPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'BDGE';
public function getTypeName() {
return pht('Badge');
}
public function newObject() {
return new PhabricatorBadgesBadge();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorBadgesQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$badge = $objects[$phid];
$id = $badge->getID();
$name = $badge->getName();
if ($badge->isArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
$handle->setName($name);
$handle->setURI("/badges/view/{$id}/");
}
}
}
diff --git a/src/applications/badges/query/PhabricatorBadgesAwardQuery.php b/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
index 57e53a5a30..ff975cf631 100644
--- a/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
+++ b/src/applications/badges/query/PhabricatorBadgesAwardQuery.php
@@ -1,121 +1,121 @@
<?php
final class PhabricatorBadgesAwardQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $badgePHIDs;
private $recipientPHIDs;
private $awarderPHIDs;
private $badgeStatuses = null;
protected function willFilterPage(array $awards) {
$badge_phids = array();
foreach ($awards as $key => $award) {
$badge_phids[] = $award->getBadgePHID();
}
$badges = id(new PhabricatorBadgesQuery())
->setViewer($this->getViewer())
->withPHIDs($badge_phids)
->execute();
$badges = mpull($badges, null, 'getPHID');
foreach ($awards as $key => $award) {
$award_badge = idx($badges, $award->getBadgePHID());
if (!$award_badge) {
unset($awards[$key]);
$this->didRejectResult($award);
continue;
}
$award->attachBadge($award_badge);
}
return $awards;
}
public function withBadgePHIDs(array $phids) {
$this->badgePHIDs = $phids;
return $this;
}
public function withRecipientPHIDs(array $phids) {
$this->recipientPHIDs = $phids;
return $this;
}
public function withAwarderPHIDs(array $phids) {
$this->awarderPHIDs = $phids;
return $this;
}
public function withBadgeStatuses(array $statuses) {
$this->badgeStatuses = $statuses;
return $this;
}
private function shouldJoinBadge() {
return (bool)$this->badgeStatuses;
}
public function newResultObject() {
return new PhabricatorBadgesAward();
}
protected function getPrimaryTableAlias() {
return 'badges_award';
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->badgePHIDs !== null) {
$where[] = qsprintf(
$conn,
'badges_award.badgePHID IN (%Ls)',
$this->badgePHIDs);
}
if ($this->recipientPHIDs !== null) {
$where[] = qsprintf(
$conn,
'badges_award.recipientPHID IN (%Ls)',
$this->recipientPHIDs);
}
if ($this->awarderPHIDs !== null) {
$where[] = qsprintf(
$conn,
'badges_award.awarderPHID IN (%Ls)',
$this->awarderPHIDs);
}
if ($this->badgeStatuses !== null) {
$where[] = qsprintf(
$conn,
'badges_badge.status IN (%Ls)',
$this->badgeStatuses);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$join = parent::buildJoinClauseParts($conn);
$badges = new PhabricatorBadgesBadge();
if ($this->shouldJoinBadge()) {
$join[] = qsprintf(
$conn,
'JOIN %T badges_badge ON badges_award.badgePHID = badges_badge.phid',
$badges->getTableName());
}
return $join;
}
public function getQueryApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
}
diff --git a/src/applications/badges/query/PhabricatorBadgesQuery.php b/src/applications/badges/query/PhabricatorBadgesQuery.php
index cc59465f67..6fb61d01c0 100644
--- a/src/applications/badges/query/PhabricatorBadgesQuery.php
+++ b/src/applications/badges/query/PhabricatorBadgesQuery.php
@@ -1,115 +1,115 @@
<?php
final class PhabricatorBadgesQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $qualities;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withQualities(array $qualities) {
$this->qualities = $qualities;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
id(new PhabricatorBadgesBadgeNameNgrams()),
$ngrams);
}
protected function getPrimaryTableAlias() {
return 'badges';
}
public function newResultObject() {
return new PhabricatorBadgesBadge();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'badges.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'badges.phid IN (%Ls)',
$this->phids);
}
if ($this->qualities !== null) {
$where[] = qsprintf(
$conn,
'badges.quality IN (%Ls)',
$this->qualities);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'badges.status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
public function getBuiltinOrders() {
return array(
'quality' => array(
'vector' => array('quality', 'id'),
'name' => pht('Rarity (Rarest First)'),
),
'shoddiness' => array(
'vector' => array('-quality', '-id'),
'name' => pht('Rarity (Most Common First)'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return array(
'quality' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'quality',
'reverse' => true,
'type' => 'int',
),
) + parent::getOrderableColumns();
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'quality' => $object->getQuality(),
);
}
}
diff --git a/src/applications/badges/query/PhabricatorBadgesSearchEngine.php b/src/applications/badges/query/PhabricatorBadgesSearchEngine.php
index 6e84c30bc9..b08962ed4b 100644
--- a/src/applications/badges/query/PhabricatorBadgesSearchEngine.php
+++ b/src/applications/badges/query/PhabricatorBadgesSearchEngine.php
@@ -1,157 +1,157 @@
<?php
final class PhabricatorBadgesSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Badges');
}
public function getApplicationClassName() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
public function newQuery() {
return new PhabricatorBadgesQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('name')
->setDescription(pht('Search for badges by name substring.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('qualities')
->setLabel(pht('Quality'))
->setEnableForConduit(false)
->setOptions(PhabricatorBadgesQuality::getDropdownQualityMap()),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(
id(new PhabricatorBadgesBadge())
->getStatusNameMap()),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['qualities']) {
$query->withQualities($map['qualities']);
}
if ($map['name'] !== null) {
$query->withNameNgrams($map['name']);
}
return $query;
}
protected function getURI($path) {
return '/badges/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['open'] = pht('Active Badges');
$names['all'] = pht('All Badges');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'open':
return $query->setParameter(
'statuses',
array(
PhabricatorBadgesBadge::STATUS_ACTIVE,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $badges,
PhabricatorSavedQuery $query) {
$phids = array();
return $phids;
}
protected function renderResultList(
array $badges,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($badges, 'PhabricatorBadgesBadge');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView());
foreach ($badges as $badge) {
$quality_name = PhabricatorBadgesQuality::getQualityName(
$badge->getQuality());
$mini_badge = id(new PHUIBadgeMiniView())
->setHeader($badge->getName())
->setIcon($badge->getIcon())
->setQuality($badge->getQuality());
$item = id(new PHUIObjectItemView())
->setHeader($badge->getName())
->setBadge($mini_badge)
->setHref('/badges/view/'.$badge->getID().'/')
->addAttribute($quality_name)
->addAttribute($badge->getFlavor());
if ($badge->isArchived()) {
$item->setDisabled(true);
$item->addIcon('fa-ban', pht('Archived'));
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No badges found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Badge'))
->setHref('/badges/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Badges let you award and distinguish special users '.
'throughout your install.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/badges/typeahead/PhabricatorBadgesDatasource.php b/src/applications/badges/typeahead/PhabricatorBadgesDatasource.php
index 458c9230d5..5fba42b933 100644
--- a/src/applications/badges/typeahead/PhabricatorBadgesDatasource.php
+++ b/src/applications/badges/typeahead/PhabricatorBadgesDatasource.php
@@ -1,69 +1,69 @@
<?php
final class PhabricatorBadgesDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Badges');
}
public function getPlaceholderText() {
return pht('Type a badge name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorBadgesApplication';
+ return PhabricatorBadgesApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$params = $this->getParameters();
$recipient_phid = $params['recipientPHID'];
$badges = id(new PhabricatorBadgesQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$awards = id(new PhabricatorBadgesAwardQuery())
->setViewer($viewer)
->withAwarderPHIDs(array($viewer->getPHID()))
->withRecipientPHIDs(array($recipient_phid))
->execute();
$awards = mpull($awards, null, 'getBadgePHID');
$results = array();
foreach ($badges as $badge) {
$closed = null;
$badge_awards = idx($awards, $badge->getPHID(), null);
if ($badge_awards) {
$closed = pht('Already awarded');
}
$status = $badge->getStatus();
if ($status === PhabricatorBadgesBadge::STATUS_ARCHIVED) {
$closed = pht('Archived');
}
$results[] = id(new PhabricatorTypeaheadResult())
->setName($badge->getName())
->setIcon($badge->getIcon())
->setColor(
PhabricatorBadgesQuality::getQualityColor($badge->getQuality()))
->setClosed($closed)
->setPHID($badge->getPHID());
}
$results = $this->filterResultsAgainstTokens($results);
return $results;
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditEngine.php
index 1b23b13fbf..3737dc9ac1 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarEventEditEngine.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditEngine.php
@@ -1,419 +1,419 @@
<?php
final class PhabricatorCalendarEventEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'calendar.event';
private $rawTransactions;
private $seriesEditMode = self::MODE_THIS;
const MODE_THIS = 'this';
const MODE_FUTURE = 'future';
public function setSeriesEditMode($series_edit_mode) {
$this->seriesEditMode = $series_edit_mode;
return $this;
}
public function getSeriesEditMode() {
return $this->seriesEditMode;
}
public function getEngineName() {
return pht('Calendar Events');
}
public function getSummaryHeader() {
return pht('Configure Calendar Event Forms');
}
public function getSummaryText() {
return pht('Configure how users create and edit events.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function newEditableObject() {
return PhabricatorCalendarEvent::initializeNewCalendarEvent(
$this->getViewer());
}
protected function newObjectQuery() {
return new PhabricatorCalendarEventQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Event');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Event: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
protected function getObjectCreateShortText() {
return pht('Create Event');
}
protected function getObjectName() {
return pht('Event');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('event/edit/');
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
if ($this->getIsCreate()) {
$invitee_phids = array($viewer->getPHID());
} else {
$invitee_phids = $object->getInviteePHIDsForEdit();
}
$frequency_map = PhabricatorCalendarEvent::getFrequencyMap();
$frequency_options = ipull($frequency_map, 'label');
$rrule = $object->newRecurrenceRule();
if ($rrule) {
$frequency = $rrule->getFrequency();
} else {
$frequency = null;
}
// At least for now, just hide "Invitees" when editing all future events.
// This may eventually deserve a more nuanced approach.
$is_future = ($this->getSeriesEditMode() == self::MODE_FUTURE);
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the event.'))
->setIsRequired(true)
->setTransactionType(
PhabricatorCalendarEventNameTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Rename the event.'))
->setConduitTypeDescription(pht('New event name.'))
->setValue($object->getName()),
id(new PhabricatorBoolEditField())
->setIsLockable(false)
->setIsDefaultable(false)
->setKey('isAllDay')
->setOptions(pht('Normal Event'), pht('All Day Event'))
->setAsCheckbox(true)
->setTransactionType(
PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE)
->setDescription(pht('Marks this as an all day event.'))
->setConduitDescription(pht('Make the event an all day event.'))
->setConduitTypeDescription(pht('Mark the event as an all day event.'))
->setValue($object->getIsAllDay()),
id(new PhabricatorEpochEditField())
->setKey('start')
->setLabel(pht('Start'))
->setIsLockable(false)
->setIsDefaultable(false)
->setTransactionType(
PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('Start time of the event.'))
->setConduitDescription(pht('Change the start time of the event.'))
->setConduitTypeDescription(pht('New event start time.'))
->setValue($object->getStartDateTimeEpoch()),
id(new PhabricatorEpochEditField())
->setKey('end')
->setLabel(pht('End'))
->setIsLockable(false)
->setIsDefaultable(false)
->setTransactionType(
PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('End time of the event.'))
->setConduitDescription(pht('Change the end time of the event.'))
->setConduitTypeDescription(pht('New event end time.'))
->setValue($object->newEndDateTimeForEdit()->getEpoch()),
id(new PhabricatorBoolEditField())
->setKey('cancelled')
->setOptions(pht('Active'), pht('Cancelled'))
->setLabel(pht('Cancelled'))
->setDescription(pht('Cancel the event.'))
->setTransactionType(
PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Cancel or restore the event.'))
->setConduitTypeDescription(pht('True to cancel the event.'))
->setValue($object->getIsCancelled()),
id(new PhabricatorUsersEditField())
->setIsLockable(false)
->setIsDefaultable(false)
->setKey('hostPHID')
->setAliases(array('host'))
->setLabel(pht('Host'))
->setDescription(pht('Host of the event.'))
->setTransactionType(
PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE)
->setIsFormField(!$this->getIsCreate())
->setConduitDescription(pht('Change the host of the event.'))
->setConduitTypeDescription(pht('New event host.'))
->setSingleValue($object->getHostPHID()),
id(new PhabricatorDatasourceEditField())
->setIsLockable(false)
->setIsDefaultable(false)
->setIsHidden($is_future)
->setKey('inviteePHIDs')
->setAliases(array('invite', 'invitee', 'invitees', 'inviteePHID'))
->setLabel(pht('Invitees'))
->setDatasource(new PhabricatorMetaMTAMailableDatasource())
->setTransactionType(
PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE)
->setDescription(pht('Users invited to the event.'))
->setConduitDescription(pht('Change invited users.'))
->setConduitTypeDescription(pht('New event invitees.'))
->setValue($invitee_phids)
->setCommentActionLabel(pht('Change Invitees')),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Description of the event.'))
->setTransactionType(
PhabricatorCalendarEventDescriptionTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Update the event description.'))
->setConduitTypeDescription(pht('New event description.'))
->setValue($object->getDescription()),
id(new PhabricatorIconSetEditField())
->setKey('icon')
->setLabel(pht('Icon'))
->setIconSet(new PhabricatorCalendarIconSet())
->setTransactionType(
PhabricatorCalendarEventIconTransaction::TRANSACTIONTYPE)
->setDescription(pht('Event icon.'))
->setConduitDescription(pht('Change the event icon.'))
->setConduitTypeDescription(pht('New event icon.'))
->setValue($object->getIcon()),
// NOTE: We're being a little sneaky here. This field is hidden and
// always has the value "true", so it makes the event recurring when you
// submit a form which contains the field. Then we put the the field on
// the "recurring" page in the "Make Recurring" dialog to simplify the
// workflow. This is still normal, explicit field from the perspective
// of the API.
id(new PhabricatorBoolEditField())
->setIsHidden(true)
->setIsLockable(false)
->setIsDefaultable(false)
->setKey('isRecurring')
->setLabel(pht('Recurring'))
->setOptions(pht('One-Time Event'), pht('Recurring Event'))
->setTransactionType(
PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE)
->setDescription(pht('One time or recurring event.'))
->setConduitDescription(pht('Make the event recurring.'))
->setConduitTypeDescription(pht('Mark the event as a recurring event.'))
->setValue(true),
id(new PhabricatorSelectEditField())
->setIsLockable(false)
->setIsDefaultable(false)
->setKey('frequency')
->setLabel(pht('Frequency'))
->setOptions($frequency_options)
->setTransactionType(
PhabricatorCalendarEventFrequencyTransaction::TRANSACTIONTYPE)
->setDescription(pht('Recurring event frequency.'))
->setConduitDescription(pht('Change the event frequency.'))
->setConduitTypeDescription(pht('New event frequency.'))
->setValue($frequency),
id(new PhabricatorEpochEditField())
->setIsLockable(false)
->setIsDefaultable(false)
->setAllowNull(true)
->setHideTime($object->getIsAllDay())
->setKey('until')
->setLabel(pht('Repeat Until'))
->setTransactionType(
PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE)
->setDescription(pht('Last instance of the event.'))
->setConduitDescription(pht('Change when the event repeats until.'))
->setConduitTypeDescription(pht('New final event time.'))
->setValue($object->getUntilDateTimeEpoch()),
);
return $fields;
}
protected function willBuildEditForm($object, array $fields) {
$all_day_field = idx($fields, 'isAllDay');
$start_field = idx($fields, 'start');
$end_field = idx($fields, 'end');
if ($all_day_field) {
$is_all_day = $all_day_field->getValueForTransaction();
$control_ids = array();
if ($start_field) {
$control_ids[] = $start_field->getControlID();
}
if ($end_field) {
$control_ids[] = $end_field->getControlID();
}
Javelin::initBehavior(
'event-all-day',
array(
'allDayID' => $all_day_field->getControlID(),
'controlIDs' => $control_ids,
));
} else {
$is_all_day = $object->getIsAllDay();
}
if ($is_all_day) {
if ($start_field) {
$start_field->setHideTime(true);
}
if ($end_field) {
$end_field->setHideTime(true);
}
}
return $fields;
}
protected function newPages($object) {
// Controls for event recurrence behavior go on a separate page which we
// put in a dialog. This simplifies event creation in the common case.
return array(
id(new PhabricatorEditPage())
->setKey('core')
->setLabel(pht('Core'))
->setIsDefault(true),
id(new PhabricatorEditPage())
->setKey('recurring')
->setLabel(pht('Recurrence'))
->setFieldKeys(
array(
'isRecurring',
'frequency',
'until',
)),
);
}
protected function willApplyTransactions($object, array $xactions) {
$viewer = $this->getViewer();
$is_parent = $object->isParentEvent();
$is_child = $object->isChildEvent();
$is_future = ($this->getSeriesEditMode() === self::MODE_FUTURE);
// Figure out which transactions we can apply to the whole series of events.
// Some transactions (like comments) can never be bulk applied.
$inherited_xactions = array();
foreach ($xactions as $xaction) {
$modular_type = $xaction->getModularType();
if (!($modular_type instanceof PhabricatorCalendarEventTransactionType)) {
continue;
}
$inherited_edit = $modular_type->isInheritedEdit();
if ($inherited_edit) {
$inherited_xactions[] = $xaction;
}
}
$this->rawTransactions = $this->cloneTransactions($inherited_xactions);
$must_fork = ($is_child && $is_future) ||
($is_parent && !$is_future);
// We don't need to fork when editing a parent event if none of the edits
// can transfer to child events. For example, commenting on a parent is
// fine.
if ($is_parent && !$is_future) {
if (!$inherited_xactions) {
$must_fork = false;
}
}
if ($must_fork) {
$fork_target = $object->loadForkTarget($viewer);
if ($fork_target) {
$fork_xaction = id(new PhabricatorCalendarEventTransaction())
->setTransactionType(
PhabricatorCalendarEventForkTransaction::TRANSACTIONTYPE)
->setNewValue(true);
if ($fork_target->getPHID() == $object->getPHID()) {
// We're forking the object itself, so just slip it into the
// transactions we're going to apply.
array_unshift($xactions, $fork_xaction);
} else {
// Otherwise, we're forking a different object, so we have to
// apply that separately.
$this->applyTransactions($fork_target, array($fork_xaction));
}
}
}
return $xactions;
}
protected function didApplyTransactions($object, array $xactions) {
$viewer = $this->getViewer();
if ($this->getSeriesEditMode() !== self::MODE_FUTURE) {
return;
}
$targets = $object->loadFutureEvents($viewer);
if (!$targets) {
return;
}
foreach ($targets as $target) {
$apply = $this->cloneTransactions($this->rawTransactions);
$this->applyTransactions($target, $apply);
}
}
private function applyTransactions($target, array $xactions) {
$viewer = $this->getViewer();
// TODO: This isn't the most accurate source we could use, but this mode
// is web-only for now.
$content_source = PhabricatorContentSource::newForSource(
PhabricatorWebContentSource::SOURCECONST);
$editor = id(new PhabricatorCalendarEventEditor())
->setActor($viewer)
->setContentSource($content_source)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
try {
$editor->applyTransactions($target, $xactions);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
// Just ignore any issues we run into.
}
}
private function cloneTransactions(array $xactions) {
$result = array();
foreach ($xactions as $xaction) {
$result[] = clone $xaction;
}
return $result;
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
index 9e3b23a43d..e5f5689025 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
@@ -1,375 +1,375 @@
<?php
final class PhabricatorCalendarEventEditor
extends PhabricatorApplicationTransactionEditor {
private $oldIsAllDay;
private $newIsAllDay;
public function getEditorApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Calendar');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this event.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function shouldApplyInitialEffects(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getOldIsAllDay() {
return $this->oldIsAllDay;
}
public function getNewIsAllDay() {
return $this->newIsAllDay;
}
protected function applyInitialEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$actor = $this->requireActor();
if ($object->getIsStub()) {
$this->materializeStub($object);
}
// Before doing anything, figure out if the event will be an all day event
// or not after the edit. This affects how we store datetime values, and
// whether we render times or not.
$old_allday = $object->getIsAllDay();
$new_allday = $old_allday;
$type_allday = PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() != $type_allday) {
continue;
}
$new_allday = (bool)$xaction->getNewValue();
}
$this->oldIsAllDay = $old_allday;
$this->newIsAllDay = $new_allday;
}
private function materializeStub(PhabricatorCalendarEvent $event) {
if (!$event->getIsStub()) {
throw new Exception(
pht('Can not materialize an event stub: this event is not a stub.'));
}
$actor = $this->getActor();
$invitees = $event->getInvitees();
$event->copyFromParent($actor);
$event->setIsStub(0);
$event->openTransaction();
$event->save();
foreach ($invitees as $invitee) {
$invitee
->setEventPHID($event->getPHID())
->save();
}
$event->saveTransaction();
$event->attachInvitees($invitees);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function adjustObjectForPolicyChecks(
PhabricatorLiskDAO $object,
array $xactions) {
$copy = parent::adjustObjectForPolicyChecks($object, $xactions);
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorCalendarEventHostTransaction::TRANSACTIONTYPE:
$copy->setHostPHID($xaction->getNewValue());
break;
case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
PhabricatorPolicyRule::passTransactionHintToRule(
$copy,
new PhabricatorCalendarEventInviteesPolicyRule(),
array_fuse($xaction->getNewValue()));
break;
}
}
return $copy;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// Clear the availability caches for users whose availability is affected
// by this edit.
$phids = mpull($object->getInvitees(), 'getInviteePHID');
$phids = array_fuse($phids);
$invalidate_all = false;
$invalidate_phids = array();
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE:
case PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE:
case PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE:
case PhabricatorCalendarEventCancelTransaction::TRANSACTIONTYPE:
case PhabricatorCalendarEventAllDayTransaction::TRANSACTIONTYPE:
// For these kinds of changes, we need to invalidate the availabilty
// caches for all attendees.
$invalidate_all = true;
break;
case PhabricatorCalendarEventAcceptTransaction::TRANSACTIONTYPE:
case PhabricatorCalendarEventDeclineTransaction::TRANSACTIONTYPE:
$acting_phid = $this->getActingAsPHID();
$invalidate_phids[$acting_phid] = $acting_phid;
break;
case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE:
foreach ($xaction->getOldValue() as $phid) {
// Add the possibly un-invited user to the list of potentially
// affected users if they are't already present.
$phids[$phid] = $phid;
$invalidate_phids[$phid] = $phid;
}
foreach ($xaction->getNewValue() as $phid) {
$invalidate_phids[$phid] = $phid;
}
break;
}
}
if (!$invalidate_all) {
$phids = array_select_keys($phids, $invalidate_phids);
}
if ($phids) {
$object->applyViewerTimezone($this->getActor());
$user = new PhabricatorUser();
$conn_w = $user->establishConnection('w');
queryfx(
$conn_w,
'UPDATE %T SET availabilityCacheTTL = NULL
WHERE phid IN (%Ls)',
$user->getTableName(),
$phids);
}
return $xactions;
}
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$start_date_xaction =
PhabricatorCalendarEventStartDateTransaction::TRANSACTIONTYPE;
$end_date_xaction =
PhabricatorCalendarEventEndDateTransaction::TRANSACTIONTYPE;
$is_recurrence_xaction =
PhabricatorCalendarEventRecurringTransaction::TRANSACTIONTYPE;
$recurrence_end_xaction =
PhabricatorCalendarEventUntilDateTransaction::TRANSACTIONTYPE;
$start_date = $object->getStartDateTimeEpoch();
$end_date = $object->getEndDateTimeEpoch();
$recurrence_end = $object->getUntilDateTimeEpoch();
$is_recurring = $object->getIsRecurring();
$errors = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $start_date_xaction) {
$start_date = $xaction->getNewValue()->getEpoch();
} else if ($xaction->getTransactionType() == $end_date_xaction) {
$end_date = $xaction->getNewValue()->getEpoch();
} else if ($xaction->getTransactionType() == $recurrence_end_xaction) {
$recurrence_end = $xaction->getNewValue()->getEpoch();
} else if ($xaction->getTransactionType() == $is_recurrence_xaction) {
$is_recurring = $xaction->getNewValue();
}
}
if ($start_date > $end_date) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$end_date_xaction,
pht('Invalid'),
pht('End date must be after start date.'),
null);
}
if ($recurrence_end && !$is_recurring) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$recurrence_end_xaction,
pht('Invalid'),
pht('Event must be recurring to have a recurrence end date.').
null);
}
return $errors;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
if ($object->isImportedEvent()) {
return false;
}
return true;
}
protected function supportsSearch() {
return true;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
if ($object->isImportedEvent()) {
return false;
}
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Calendar]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
if ($object->getHostPHID()) {
$phids[] = $object->getHostPHID();
}
$phids[] = $this->getActingAsPHID();
$invitees = $object->getInvitees();
foreach ($invitees as $invitee) {
$status = $invitee->getStatus();
if ($status === PhabricatorCalendarEventInvitee::STATUS_ATTENDING
|| $status === PhabricatorCalendarEventInvitee::STATUS_INVITED) {
$phids[] = $invitee->getInviteePHID();
}
}
$phids = array_unique($phids);
return $phids;
}
public function getMailTagsMap() {
return array(
PhabricatorCalendarEventTransaction::MAILTAG_CONTENT =>
pht(
"An event's name, status, invite list, ".
"icon, and description changes."),
PhabricatorCalendarEventTransaction::MAILTAG_RESCHEDULE =>
pht(
"An event's start and end date ".
"and cancellation status changes."),
PhabricatorCalendarEventTransaction::MAILTAG_OTHER =>
pht('Other event activity not listed above occurs.'),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorCalendarReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
$monogram = $object->getMonogram();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$description = $object->getDescription();
if ($this->getIsNewObject()) {
if (strlen($description)) {
$body->addRemarkupSection(
pht('EVENT DESCRIPTION'),
$description);
}
}
$body->addLinkSection(
pht('EVENT DETAIL'),
PhabricatorEnv::getProductionURI($object->getURI()));
$ics_attachment = $this->newICSAttachment($object);
$body->addAttachment($ics_attachment);
return $body;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new PhabricatorCalendarEventHeraldAdapter())
->setObject($object);
}
private function newICSAttachment(
PhabricatorCalendarEvent $event) {
$actor = $this->getActor();
$ics_data = id(new PhabricatorCalendarICSWriter())
->setViewer($actor)
->setEvents(array($event))
->writeICSDocument();
$ics_attachment = new PhabricatorMailAttachment(
$ics_data,
$event->getICSFilename(),
'text/calendar');
return $ics_attachment;
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
index bc8fc360c6..b1268f1f4b 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditEngine.php
@@ -1,133 +1,133 @@
<?php
final class PhabricatorCalendarExportEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'calendar.export';
public function getEngineName() {
return pht('Calendar Exports');
}
public function isEngineConfigurable() {
return false;
}
public function getSummaryHeader() {
return pht('Configure Calendar Export Forms');
}
public function getSummaryText() {
return pht('Configure how users create and edit exports.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function newEditableObject() {
return PhabricatorCalendarExport::initializeNewCalendarExport(
$this->getViewer());
}
protected function newObjectQuery() {
return new PhabricatorCalendarExportQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Export');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Export: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Export %d', $object->getID());
}
protected function getObjectCreateShortText() {
return pht('Create Export');
}
protected function getObjectName() {
return pht('Export');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('export/edit/');
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$export_modes = PhabricatorCalendarExport::getAvailablePolicyModes();
$export_modes = array_fuse($export_modes);
$current_mode = $object->getPolicyMode();
if (empty($export_modes[$current_mode])) {
array_unshift($export_modes, $current_mode);
}
$mode_options = array();
foreach ($export_modes as $export_mode) {
$mode_name = PhabricatorCalendarExport::getPolicyModeName($export_mode);
$mode_summary = PhabricatorCalendarExport::getPolicyModeSummary(
$export_mode);
$mode_options[$export_mode] = pht('%s: %s', $mode_name, $mode_summary);
}
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the export.'))
->setIsRequired(true)
->setTransactionType(
PhabricatorCalendarExportNameTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Rename the export.'))
->setConduitTypeDescription(pht('New export name.'))
->setValue($object->getName()),
id(new PhabricatorBoolEditField())
->setKey('disabled')
->setOptions(pht('Active'), pht('Disabled'))
->setLabel(pht('Disabled'))
->setDescription(pht('Disable the export.'))
->setTransactionType(
PhabricatorCalendarExportDisableTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Disable or restore the export.'))
->setConduitTypeDescription(pht('True to cancel the export.'))
->setValue($object->getIsDisabled()),
id(new PhabricatorTextEditField())
->setKey('queryKey')
->setLabel(pht('Query Key'))
->setDescription(pht('Query to execute.'))
->setIsRequired(true)
->setTransactionType(
PhabricatorCalendarExportQueryKeyTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Change the export query key.'))
->setConduitTypeDescription(pht('New export query key.'))
->setValue($object->getQueryKey()),
id(new PhabricatorSelectEditField())
->setKey('mode')
->setLabel(pht('Mode'))
->setTransactionType(
PhabricatorCalendarExportModeTransaction::TRANSACTIONTYPE)
->setOptions($mode_options)
->setDescription(pht('Change the policy mode for the export.'))
->setConduitDescription(pht('Adjust export mode.'))
->setConduitTypeDescription(pht('New export mode.'))
->setValue($current_mode),
);
return $fields;
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
index 6ddd172d58..e8ec5601f7 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarExportEditor.php
@@ -1,18 +1,18 @@
<?php
final class PhabricatorCalendarExportEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Calendar Exports');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this export.', $author);
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarImportEditEngine.php b/src/applications/calendar/editor/PhabricatorCalendarImportEditEngine.php
index 7be3969671..210efe6961 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarImportEditEngine.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarImportEditEngine.php
@@ -1,155 +1,155 @@
<?php
final class PhabricatorCalendarImportEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'calendar.import';
private $importEngine;
public function setImportEngine(PhabricatorCalendarImportEngine $engine) {
$this->importEngine = $engine;
return $this;
}
public function getImportEngine() {
return $this->importEngine;
}
public function getEngineName() {
return pht('Calendar Imports');
}
public function isEngineConfigurable() {
return false;
}
public function getSummaryHeader() {
return pht('Configure Calendar Import Forms');
}
public function getSummaryText() {
return pht('Configure how users create and edit imports.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$engine = $this->getImportEngine();
return PhabricatorCalendarImport::initializeNewCalendarImport(
$viewer,
$engine);
}
protected function newObjectQuery() {
return new PhabricatorCalendarImportQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Import');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Import: %s', $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return pht('Import %d', $object->getID());
}
protected function getObjectCreateShortText() {
return pht('Create Import');
}
protected function getObjectName() {
return pht('Import');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('import/edit/');
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$engine = $object->getEngine();
$can_trigger = $engine->supportsTriggers($object);
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the import.'))
->setTransactionType(
PhabricatorCalendarImportNameTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Rename the import.'))
->setConduitTypeDescription(pht('New import name.'))
->setPlaceholder($object->getDisplayName())
->setValue($object->getName()),
id(new PhabricatorBoolEditField())
->setKey('disabled')
->setOptions(pht('Active'), pht('Disabled'))
->setLabel(pht('Disabled'))
->setDescription(pht('Disable the import.'))
->setTransactionType(
PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Disable or restore the import.'))
->setConduitTypeDescription(pht('True to cancel the import.'))
->setValue($object->getIsDisabled()),
id(new PhabricatorBoolEditField())
->setKey('delete')
->setLabel(pht('Delete Imported Events'))
->setDescription(pht('Delete all events from this source.'))
->setTransactionType(
PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Disable or restore the import.'))
->setConduitTypeDescription(pht('True to delete imported events.'))
->setValue(false),
id(new PhabricatorBoolEditField())
->setKey('reload')
->setLabel(pht('Reload Import'))
->setDescription(pht('Reload events imported from this source.'))
->setTransactionType(
PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Disable or restore the import.'))
->setConduitTypeDescription(pht('True to reload the import.'))
->setValue(false),
);
if ($can_trigger) {
$frequency_map = PhabricatorCalendarImport::getTriggerFrequencyMap();
$frequency_options = ipull($frequency_map, 'name');
$fields[] = id(new PhabricatorSelectEditField())
->setKey('frequency')
->setLabel(pht('Update Automatically'))
->setDescription(pht('Configure an automatic update frequency.'))
->setTransactionType(
PhabricatorCalendarImportFrequencyTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('Set the automatic update frequency.'))
->setConduitTypeDescription(pht('Update frequency constant.'))
->setValue($object->getTriggerFrequency())
->setOptions($frequency_options);
}
$import_engine = $object->getEngine();
foreach ($import_engine->newEditEngineFields($this, $object) as $field) {
$fields[] = $field;
}
return $fields;
}
}
diff --git a/src/applications/calendar/editor/PhabricatorCalendarImportEditor.php b/src/applications/calendar/editor/PhabricatorCalendarImportEditor.php
index f83869d7b9..f168523988 100644
--- a/src/applications/calendar/editor/PhabricatorCalendarImportEditor.php
+++ b/src/applications/calendar/editor/PhabricatorCalendarImportEditor.php
@@ -1,141 +1,141 @@
<?php
final class PhabricatorCalendarImportEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Calendar Imports');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this import.', $author);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$actor = $this->getActor();
// We import events when you create a source, or if you later reload it
// explicitly.
$should_reload = $this->getIsNewObject();
// We adjust the import trigger if you change the import frequency or
// disable the import.
$should_trigger = false;
foreach ($xactions as $xaction) {
$xaction_type = $xaction->getTransactionType();
switch ($xaction_type) {
case PhabricatorCalendarImportReloadTransaction::TRANSACTIONTYPE:
$should_reload = true;
break;
case PhabricatorCalendarImportFrequencyTransaction::TRANSACTIONTYPE:
$should_trigger = true;
break;
case PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE:
$should_trigger = true;
break;
}
}
if ($should_reload) {
$import_engine = $object->getEngine();
$import_engine->importEventsFromSource($actor, $object, true);
}
if ($should_trigger) {
$trigger_phid = $object->getTriggerPHID();
if ($trigger_phid) {
$trigger = id(new PhabricatorWorkerTriggerQuery())
->setViewer($actor)
->withPHIDs(array($trigger_phid))
->executeOne();
if ($trigger) {
$engine = new PhabricatorDestructionEngine();
$engine->destroyObject($trigger);
}
}
$frequency = $object->getTriggerFrequency();
$now = PhabricatorTime::getNow();
switch ($frequency) {
case PhabricatorCalendarImport::FREQUENCY_ONCE:
$clock = null;
break;
case PhabricatorCalendarImport::FREQUENCY_HOURLY:
$clock = new PhabricatorMetronomicTriggerClock(
array(
'period' => phutil_units('1 hour in seconds'),
));
break;
case PhabricatorCalendarImport::FREQUENCY_DAILY:
$clock = new PhabricatorDailyRoutineTriggerClock(
array(
'start' => $now,
));
break;
default:
throw new Exception(
pht(
'Unknown import trigger frequency "%s".',
$frequency));
}
// If the object has been disabled, don't write a new trigger.
if ($object->getIsDisabled()) {
$clock = null;
}
if ($clock) {
$trigger_action = new PhabricatorScheduleTaskTriggerAction(
array(
'class' => 'PhabricatorCalendarImportReloadWorker',
'data' => array(
'importPHID' => $object->getPHID(),
'via' => PhabricatorCalendarImportReloadWorker::VIA_TRIGGER,
),
'options' => array(
'objectPHID' => $object->getPHID(),
'priority' => PhabricatorWorker::PRIORITY_BULK,
),
));
$trigger_phid = PhabricatorPHID::generateNewPHID(
PhabricatorWorkerTriggerPHIDType::TYPECONST);
$object
->setTriggerPHID($trigger_phid)
->save();
$trigger = id(new PhabricatorWorkerTrigger())
->setClock($clock)
->setAction($trigger_action)
->setPHID($trigger_phid)
->save();
} else {
$object
->setTriggerPHID(null)
->save();
}
}
return $xactions;
}
}
diff --git a/src/applications/calendar/herald/PhabricatorCalendarEventHeraldAdapter.php b/src/applications/calendar/herald/PhabricatorCalendarEventHeraldAdapter.php
index 49d5f38959..59982cecbc 100644
--- a/src/applications/calendar/herald/PhabricatorCalendarEventHeraldAdapter.php
+++ b/src/applications/calendar/herald/PhabricatorCalendarEventHeraldAdapter.php
@@ -1,56 +1,56 @@
<?php
final class PhabricatorCalendarEventHeraldAdapter extends HeraldAdapter {
private $object;
public function getAdapterApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to events being created or updated.');
}
protected function newObject() {
return new PhabricatorCalendarEvent();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PhabricatorCalendarEvent);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when an event is created or updated.');
}
public function setObject($object) {
$this->object = $object;
return $this;
}
public function getObject() {
return $this->object;
}
public function getAdapterContentName() {
return pht('Calendar Events');
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function getHeraldName() {
return $this->getObject()->getMonogram();
}
}
diff --git a/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php
index fd8e86a1f2..9048a7d208 100644
--- a/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php
+++ b/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php
@@ -1,78 +1,78 @@
<?php
final class PhabricatorCalendarEventPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CEVT';
public function getTypeName() {
return pht('Event');
}
public function newObject() {
return new PhabricatorCalendarEvent();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCalendarEventQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$event = $objects[$phid];
$monogram = $event->getMonogram();
$name = $event->getName();
$uri = $event->getURI();
$handle
->setName($name)
->setFullName(pht('%s: %s', $monogram, $name))
->setURI($uri);
if ($event->getIsCancelled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^E[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorCalendarEventQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php
index c642632ca8..eaf4562150 100644
--- a/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php
+++ b/src/applications/calendar/phid/PhabricatorCalendarExportPHIDType.php
@@ -1,50 +1,50 @@
<?php
final class PhabricatorCalendarExportPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CEXP';
public function getTypeName() {
return pht('Calendar Export');
}
public function newObject() {
return new PhabricatorCalendarExport();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCalendarExportQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$export = $objects[$phid];
$id = $export->getID();
$name = $export->getName();
$uri = $export->getURI();
$handle
->setName($name)
->setFullName(pht('Calendar Export %s: %s', $id, $name))
->setURI($uri);
if ($export->getIsDisabled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/calendar/phid/PhabricatorCalendarExternalInviteePHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarExternalInviteePHIDType.php
index a5e86893ac..6e50246bb0 100644
--- a/src/applications/calendar/phid/PhabricatorCalendarExternalInviteePHIDType.php
+++ b/src/applications/calendar/phid/PhabricatorCalendarExternalInviteePHIDType.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorCalendarExternalInviteePHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'CXNV';
public function getTypeName() {
return pht('External Invitee');
}
public function newObject() {
return new PhabricatorCalendarExternalInvitee();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCalendarExternalInviteeQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$invitee = $objects[$phid];
$name = $invitee->getName();
$handle->setName($name);
}
}
}
diff --git a/src/applications/calendar/phid/PhabricatorCalendarImportPHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarImportPHIDType.php
index 876ec7acf7..32118f4fd4 100644
--- a/src/applications/calendar/phid/PhabricatorCalendarImportPHIDType.php
+++ b/src/applications/calendar/phid/PhabricatorCalendarImportPHIDType.php
@@ -1,50 +1,50 @@
<?php
final class PhabricatorCalendarImportPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CIMP';
public function getTypeName() {
return pht('Calendar Import');
}
public function newObject() {
return new PhabricatorCalendarImport();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCalendarImportQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$import = $objects[$phid];
$id = $import->getID();
$name = $import->getDisplayName();
$uri = $import->getURI();
$handle
->setName($name)
->setFullName(pht('Calendar Import %s: %s', $id, $name))
->setURI($uri);
if ($import->getIsDisabled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
index 683d6cd918..2db8cdfdea 100644
--- a/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php
@@ -1,99 +1,99 @@
<?php
final class PhabricatorCalendarEventInviteeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $eventPHIDs;
private $inviteePHIDs;
private $inviterPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withEventPHIDs(array $phids) {
$this->eventPHIDs = $phids;
return $this;
}
public function withInviteePHIDs(array $phids) {
$this->inviteePHIDs = $phids;
return $this;
}
public function withInviterPHIDs(array $phids) {
$this->inviterPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
protected function loadPage() {
$table = new PhabricatorCalendarEventInvitee();
$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->eventPHIDs !== null) {
$where[] = qsprintf(
$conn,
'eventPHID IN (%Ls)',
$this->eventPHIDs);
}
if ($this->inviteePHIDs !== null) {
$where[] = qsprintf(
$conn,
'inviteePHID IN (%Ls)',
$this->inviteePHIDs);
}
if ($this->inviterPHIDs !== null) {
$where[] = qsprintf(
$conn,
'inviterPHID IN (%Ls)',
$this->inviterPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status = %d',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
index d20250e711..90f0bab517 100644
--- a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
@@ -1,751 +1,751 @@
<?php
final class PhabricatorCalendarEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $rangeBegin;
private $rangeEnd;
private $inviteePHIDs;
private $hostPHIDs;
private $isCancelled;
private $eventsWithNoParent;
private $instanceSequencePairs;
private $isStub;
private $parentEventPHIDs;
private $importSourcePHIDs;
private $importAuthorPHIDs;
private $importUIDs;
private $utcInitialEpochMin;
private $utcInitialEpochMax;
private $isImported;
private $needRSVPs;
private $generateGhosts = false;
public function newResultObject() {
return new PhabricatorCalendarEvent();
}
public function setGenerateGhosts($generate_ghosts) {
$this->generateGhosts = $generate_ghosts;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDateRange($begin, $end) {
$this->rangeBegin = $begin;
$this->rangeEnd = $end;
return $this;
}
public function withUTCInitialEpochBetween($min, $max) {
$this->utcInitialEpochMin = $min;
$this->utcInitialEpochMax = $max;
return $this;
}
public function withInvitedPHIDs(array $phids) {
$this->inviteePHIDs = $phids;
return $this;
}
public function withHostPHIDs(array $phids) {
$this->hostPHIDs = $phids;
return $this;
}
public function withIsCancelled($is_cancelled) {
$this->isCancelled = $is_cancelled;
return $this;
}
public function withIsStub($is_stub) {
$this->isStub = $is_stub;
return $this;
}
public function withEventsWithNoParent($events_with_no_parent) {
$this->eventsWithNoParent = $events_with_no_parent;
return $this;
}
public function withInstanceSequencePairs(array $pairs) {
$this->instanceSequencePairs = $pairs;
return $this;
}
public function withParentEventPHIDs(array $parent_phids) {
$this->parentEventPHIDs = $parent_phids;
return $this;
}
public function withImportSourcePHIDs(array $import_phids) {
$this->importSourcePHIDs = $import_phids;
return $this;
}
public function withImportAuthorPHIDs(array $author_phids) {
$this->importAuthorPHIDs = $author_phids;
return $this;
}
public function withImportUIDs(array $uids) {
$this->importUIDs = $uids;
return $this;
}
public function withIsImported($is_imported) {
$this->isImported = $is_imported;
return $this;
}
public function needRSVPs(array $phids) {
$this->needRSVPs = $phids;
return $this;
}
protected function getDefaultOrderVector() {
return array('start', 'id');
}
public function getBuiltinOrders() {
return array(
'start' => array(
'vector' => array('start', 'id'),
'name' => pht('Event Start'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return array(
'start' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'utcInitialEpoch',
'reverse' => true,
'type' => 'int',
'unique' => false,
),
) + parent::getOrderableColumns();
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'start' => (int)$object->getStartDateTimeEpoch(),
);
}
protected function shouldLimitResults() {
// When generating ghosts, we can't rely on database ordering because
// MySQL can't predict the ghost start times. We'll just load all matching
// events, then generate results from there.
if ($this->generateGhosts) {
return false;
}
return true;
}
protected function loadPage() {
$events = $this->loadStandardPage($this->newResultObject());
$viewer = $this->getViewer();
foreach ($events as $event) {
$event->applyViewerTimezone($viewer);
}
if (!$this->generateGhosts) {
return $events;
}
$raw_limit = $this->getRawResultLimit();
if (!$raw_limit && !$this->rangeEnd) {
throw new Exception(
pht(
'Event queries which generate ghost events must include either a '.
'result limit or an end date, because they may otherwise generate '.
'an infinite number of results. This query has neither.'));
}
foreach ($events as $key => $event) {
$sequence_start = 0;
$sequence_end = null;
$end = null;
$instance_of = $event->getInstanceOfEventPHID();
if ($instance_of == null && $this->isCancelled !== null) {
if ($event->getIsCancelled() != $this->isCancelled) {
unset($events[$key]);
continue;
}
}
}
// Pull out all of the parents first. We may discard them as we begin
// generating ghost events, but we still want to process all of them.
$parents = array();
foreach ($events as $key => $event) {
if ($event->isParentEvent()) {
$parents[$key] = $event;
}
}
// Now that we've picked out all the parent events, we can immediately
// discard anything outside of the time window.
$events = $this->getEventsInRange($events);
$generate_from = $this->rangeBegin;
$generate_until = $this->rangeEnd;
foreach ($parents as $key => $event) {
$duration = $event->getDuration();
$start_date = $this->getRecurrenceWindowStart(
$event,
$generate_from - $duration);
$end_date = $this->getRecurrenceWindowEnd(
$event,
$generate_until);
$limit = $this->getRecurrenceLimit($event, $raw_limit);
// note that this can be NULL for some imported events
$set = $event->newRecurrenceSet();
$recurrences = array();
if ($set) {
$recurrences = $set->getEventsBetween(
$start_date,
$end_date,
$limit + 1);
}
// We're generating events from the beginning and then filtering them
// here (instead of only generating events starting at the start date)
// because we need to know the proper sequence indexes to generate ghost
// events. This may change after RDATE support.
if ($start_date) {
$start_epoch = $start_date->getEpoch();
} else {
$start_epoch = null;
}
foreach ($recurrences as $sequence_index => $sequence_datetime) {
if (!$sequence_index) {
// This is the parent event, which we already have.
continue;
}
if ($start_epoch) {
if ($sequence_datetime->getEpoch() < $start_epoch) {
continue;
}
}
$events[] = $event->newGhost(
$viewer,
$sequence_index,
$sequence_datetime);
}
// NOTE: We're slicing results every time because this makes it cheaper
// to generate future ghosts. If we already have 100 events that occur
// before July 1, we know we never need to generate ghosts after that
// because they couldn't possibly ever appear in the result set.
if ($raw_limit) {
if (count($events) > $raw_limit) {
$events = msort($events, 'getStartDateTimeEpoch');
$events = array_slice($events, 0, $raw_limit, true);
$generate_until = last($events)->getEndDateTimeEpoch();
}
}
}
// Now that we're done generating ghost events, we're going to remove any
// ghosts that we have concrete events for (or which we can load the
// concrete events for). These concrete events are generated when users
// edit a ghost, and replace the ghost events.
// First, generate a map of all concrete <parentPHID, sequence> events we
// already loaded. We don't need to load these again.
$have_pairs = array();
foreach ($events as $event) {
if ($event->getIsGhostEvent()) {
continue;
}
$parent_phid = $event->getInstanceOfEventPHID();
$sequence = $event->getSequenceIndex();
$have_pairs[$parent_phid][$sequence] = true;
}
// Now, generate a map of all <parentPHID, sequence> events we generated
// ghosts for. We need to try to load these if we don't already have them.
$map = array();
$parent_pairs = array();
foreach ($events as $key => $event) {
if (!$event->getIsGhostEvent()) {
continue;
}
$parent_phid = $event->getInstanceOfEventPHID();
$sequence = $event->getSequenceIndex();
// We already loaded the concrete version of this event, so we can just
// throw out the ghost and move on.
if (isset($have_pairs[$parent_phid][$sequence])) {
unset($events[$key]);
continue;
}
// We didn't load the concrete version of this event, so we need to
// try to load it if it exists.
$parent_pairs[] = array($parent_phid, $sequence);
$map[$parent_phid][$sequence] = $key;
}
if ($parent_pairs) {
$instances = id(new self())
->setViewer($viewer)
->setParentQuery($this)
->withInstanceSequencePairs($parent_pairs)
->execute();
foreach ($instances as $instance) {
$parent_phid = $instance->getInstanceOfEventPHID();
$sequence = $instance->getSequenceIndex();
$indexes = idx($map, $parent_phid);
$key = idx($indexes, $sequence);
// Replace the ghost with the corresponding concrete event.
$events[$key] = $instance;
}
}
$events = msort($events, 'getStartDateTimeEpoch');
return $events;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn_r) {
$parts = parent::buildJoinClauseParts($conn_r);
if ($this->inviteePHIDs !== null) {
$parts[] = qsprintf(
$conn_r,
'JOIN %T invitee ON invitee.eventPHID = event.phid
AND invitee.status != %s',
id(new PhabricatorCalendarEventInvitee())->getTableName(),
PhabricatorCalendarEventInvitee::STATUS_UNINVITED);
}
return $parts;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'event.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'event.phid IN (%Ls)',
$this->phids);
}
// NOTE: The date ranges we query for are larger than the requested ranges
// because we need to catch all-day events. We'll refine this range later
// after adjusting the visible range of events we load.
if ($this->rangeBegin) {
$where[] = qsprintf(
$conn,
'(event.utcUntilEpoch >= %d) OR (event.utcUntilEpoch IS NULL)',
$this->rangeBegin - phutil_units('16 hours in seconds'));
}
if ($this->rangeEnd) {
$where[] = qsprintf(
$conn,
'event.utcInitialEpoch <= %d',
$this->rangeEnd + phutil_units('16 hours in seconds'));
}
if ($this->utcInitialEpochMin !== null) {
$where[] = qsprintf(
$conn,
'event.utcInitialEpoch >= %d',
$this->utcInitialEpochMin);
}
if ($this->utcInitialEpochMax !== null) {
$where[] = qsprintf(
$conn,
'event.utcInitialEpoch <= %d',
$this->utcInitialEpochMax);
}
if ($this->inviteePHIDs !== null) {
$where[] = qsprintf(
$conn,
'invitee.inviteePHID IN (%Ls)',
$this->inviteePHIDs);
}
if ($this->hostPHIDs !== null) {
$where[] = qsprintf(
$conn,
'event.hostPHID IN (%Ls)',
$this->hostPHIDs);
}
if ($this->isCancelled !== null) {
$where[] = qsprintf(
$conn,
'event.isCancelled = %d',
(int)$this->isCancelled);
}
if ($this->eventsWithNoParent == true) {
$where[] = qsprintf(
$conn,
'event.instanceOfEventPHID IS NULL');
}
if ($this->instanceSequencePairs !== null) {
$sql = array();
foreach ($this->instanceSequencePairs as $pair) {
$sql[] = qsprintf(
$conn,
'(event.instanceOfEventPHID = %s AND event.sequenceIndex = %d)',
$pair[0],
$pair[1]);
}
$where[] = qsprintf(
$conn,
'%LO',
$sql);
}
if ($this->isStub !== null) {
$where[] = qsprintf(
$conn,
'event.isStub = %d',
(int)$this->isStub);
}
if ($this->parentEventPHIDs !== null) {
$where[] = qsprintf(
$conn,
'event.instanceOfEventPHID IN (%Ls)',
$this->parentEventPHIDs);
}
if ($this->importSourcePHIDs !== null) {
$where[] = qsprintf(
$conn,
'event.importSourcePHID IN (%Ls)',
$this->importSourcePHIDs);
}
if ($this->importAuthorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'event.importAuthorPHID IN (%Ls)',
$this->importAuthorPHIDs);
}
if ($this->importUIDs !== null) {
$where[] = qsprintf(
$conn,
'event.importUID IN (%Ls)',
$this->importUIDs);
}
if ($this->isImported !== null) {
if ($this->isImported) {
$where[] = qsprintf(
$conn,
'event.importSourcePHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'event.importSourcePHID IS NULL');
}
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'event';
}
protected function shouldGroupQueryResultRows() {
if ($this->inviteePHIDs !== null) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
protected function willFilterPage(array $events) {
$instance_of_event_phids = array();
$recurring_events = array();
$viewer = $this->getViewer();
$events = $this->getEventsInRange($events);
$import_phids = array();
foreach ($events as $event) {
$import_phid = $event->getImportSourcePHID();
if ($import_phid !== null) {
$import_phids[$import_phid] = $import_phid;
}
}
if ($import_phids) {
$imports = id(new PhabricatorCalendarImportQuery())
->setParentQuery($this)
->setViewer($viewer)
->withPHIDs($import_phids)
->execute();
$imports = mpull($imports, null, 'getPHID');
} else {
$imports = array();
}
foreach ($events as $key => $event) {
$import_phid = $event->getImportSourcePHID();
if ($import_phid === null) {
$event->attachImportSource(null);
continue;
}
$import = idx($imports, $import_phid);
if (!$import) {
unset($events[$key]);
$this->didRejectResult($event);
continue;
}
$event->attachImportSource($import);
}
$phids = array();
foreach ($events as $event) {
$phids[] = $event->getPHID();
$instance_of = $event->getInstanceOfEventPHID();
if ($instance_of) {
$instance_of_event_phids[] = $instance_of;
}
}
if (count($instance_of_event_phids) > 0) {
$recurring_events = id(new PhabricatorCalendarEventQuery())
->setViewer($viewer)
->withPHIDs($instance_of_event_phids)
->withEventsWithNoParent(true)
->execute();
$recurring_events = mpull($recurring_events, null, 'getPHID');
}
if ($events) {
$invitees = id(new PhabricatorCalendarEventInviteeQuery())
->setViewer($viewer)
->withEventPHIDs($phids)
->execute();
$invitees = mgroup($invitees, 'getEventPHID');
} else {
$invitees = array();
}
foreach ($events as $key => $event) {
$event_invitees = idx($invitees, $event->getPHID(), array());
$event->attachInvitees($event_invitees);
$instance_of = $event->getInstanceOfEventPHID();
if (!$instance_of) {
continue;
}
$parent = idx($recurring_events, $instance_of);
// should never get here
if (!$parent) {
unset($events[$key]);
continue;
}
$event->attachParentEvent($parent);
if ($this->isCancelled !== null) {
if ($event->getIsCancelled() != $this->isCancelled) {
unset($events[$key]);
continue;
}
}
}
$events = msort($events, 'getStartDateTimeEpoch');
if ($this->needRSVPs) {
$rsvp_phids = $this->needRSVPs;
$project_type = PhabricatorProjectProjectPHIDType::TYPECONST;
$project_phids = array();
foreach ($events as $event) {
foreach ($event->getInvitees() as $invitee) {
$invitee_phid = $invitee->getInviteePHID();
if (phid_get_type($invitee_phid) == $project_type) {
$project_phids[] = $invitee_phid;
}
}
}
if ($project_phids) {
$member_type = PhabricatorProjectMaterializedMemberEdgeType::EDGECONST;
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($project_phids)
->withEdgeTypes(array($member_type))
->withDestinationPHIDs($rsvp_phids);
$edges = $query->execute();
$project_map = array();
foreach ($edges as $src => $types) {
foreach ($types as $type => $dsts) {
foreach ($dsts as $dst => $edge) {
$project_map[$dst][] = $src;
}
}
}
} else {
$project_map = array();
}
$membership_map = array();
foreach ($rsvp_phids as $rsvp_phid) {
$membership_map[$rsvp_phid] = array();
$membership_map[$rsvp_phid][] = $rsvp_phid;
$project_phids = idx($project_map, $rsvp_phid);
if ($project_phids) {
foreach ($project_phids as $project_phid) {
$membership_map[$rsvp_phid][] = $project_phid;
}
}
}
foreach ($events as $event) {
$invitees = $event->getInvitees();
$invitees = mpull($invitees, null, 'getInviteePHID');
$rsvp_map = array();
foreach ($rsvp_phids as $rsvp_phid) {
$membership_phids = $membership_map[$rsvp_phid];
$rsvps = array_select_keys($invitees, $membership_phids);
$rsvp_map[$rsvp_phid] = $rsvps;
}
$event->attachRSVPs($rsvp_map);
}
}
return $events;
}
private function getEventsInRange(array $events) {
$range_start = $this->rangeBegin;
$range_end = $this->rangeEnd;
foreach ($events as $key => $event) {
$event_start = $event->getStartDateTimeEpoch();
$event_end = $event->getEndDateTimeEpoch();
if ($range_start && $event_end < $range_start) {
unset($events[$key]);
}
if ($range_end && $event_start > $range_end) {
unset($events[$key]);
}
}
return $events;
}
private function getRecurrenceWindowStart(
PhabricatorCalendarEvent $event,
$generate_from) {
if (!$generate_from) {
return null;
}
return PhutilCalendarAbsoluteDateTime::newFromEpoch($generate_from);
}
private function getRecurrenceWindowEnd(
PhabricatorCalendarEvent $event,
$generate_until) {
$end_epochs = array();
if ($generate_until) {
$end_epochs[] = $generate_until;
}
$until_epoch = $event->getUntilDateTimeEpoch();
if ($until_epoch) {
$end_epochs[] = $until_epoch;
}
if (!$end_epochs) {
return null;
}
return PhutilCalendarAbsoluteDateTime::newFromEpoch(min($end_epochs));
}
private function getRecurrenceLimit(
PhabricatorCalendarEvent $event,
$raw_limit) {
$count = $event->getRecurrenceCount();
if ($count && ($count <= $raw_limit)) {
return ($count - 1);
}
return $raw_limit;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
index 79d4321545..3a6e931515 100644
--- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php
@@ -1,633 +1,633 @@
<?php
final class PhabricatorCalendarEventSearchEngine
extends PhabricatorApplicationSearchEngine {
private $calendarYear;
private $calendarMonth;
private $calendarDay;
public function getResultTypeDescription() {
return pht('Calendar Events');
}
public function getApplicationClassName() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function newQuery() {
$viewer = $this->requireViewer();
return id(new PhabricatorCalendarEventQuery())
->needRSVPs(array($viewer->getPHID()));
}
protected function shouldShowOrderField() {
return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Hosts'))
->setKey('hostPHIDs')
->setAliases(array('host', 'hostPHID', 'hosts'))
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Invited'))
->setKey('invitedPHIDs')
->setDatasource(new PhabricatorCalendarInviteeDatasource()),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs After'))
->setKey('rangeStart'),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs Before'))
->setKey('rangeEnd')
->setAliases(array('rangeEnd')),
id(new PhabricatorSearchCheckboxesField())
->setKey('upcoming')
->setOptions(array(
'upcoming' => pht('Show only upcoming events.'),
)),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Cancelled Events'))
->setKey('isCancelled')
->setOptions($this->getCancelledOptions())
->setDefault('active'),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Import Sources'))
->setKey('importSourcePHIDs')
->setAliases(array('importSourcePHID')),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Display Options'))
->setKey('display')
->setOptions($this->getViewOptions())
->setDefault('month'),
);
}
private function getCancelledOptions() {
return array(
'active' => pht('Active Events Only'),
'cancelled' => pht('Cancelled Events Only'),
'both' => pht('Both Cancelled and Active Events'),
);
}
private function getViewOptions() {
return array(
'month' => pht('Month View'),
'day' => pht('Day View'),
'list' => pht('List View'),
);
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = parent::buildQueryFromSavedQuery($saved);
// If this is an export query for generating an ".ics" file, don't
// build ghost events.
if ($saved->getParameter('export')) {
$query->setGenerateGhosts(false);
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$viewer = $this->requireViewer();
if ($map['hostPHIDs']) {
$query->withHostPHIDs($map['hostPHIDs']);
}
if ($map['invitedPHIDs']) {
$query->withInvitedPHIDs($map['invitedPHIDs']);
}
$range_start = $map['rangeStart'];
$range_end = $map['rangeEnd'];
$display = $map['display'];
if ($map['upcoming'] && $map['upcoming'][0] == 'upcoming') {
$upcoming = true;
} else {
$upcoming = false;
}
list($range_start, $range_end) = $this->getQueryDateRange(
$range_start,
$range_end,
$display,
$upcoming);
$query->withDateRange($range_start, $range_end);
switch ($map['isCancelled']) {
case 'active':
$query->withIsCancelled(false);
break;
case 'cancelled':
$query->withIsCancelled(true);
break;
}
if ($map['importSourcePHIDs']) {
$query->withImportSourcePHIDs($map['importSourcePHIDs']);
}
if (!$map['ids'] && !$map['phids']) {
$query
->withIsStub(false)
->setGenerateGhosts(true);
}
return $query;
}
private function getQueryDateRange(
$start_date_wild,
$end_date_wild,
$display,
$upcoming) {
$start_date_value = $this->getSafeDate($start_date_wild);
$end_date_value = $this->getSafeDate($end_date_wild);
$viewer = $this->requireViewer();
$timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
$min_range = null;
$max_range = null;
$min_range = $start_date_value->getEpoch();
$max_range = $end_date_value->getEpoch();
if ($display == 'month' || $display == 'day') {
list($start_year, $start_month, $start_day) =
$this->getDisplayYearAndMonthAndDay($min_range, $max_range, $display);
$start_day = new DateTime(
"{$start_year}-{$start_month}-{$start_day}",
$timezone);
$next = clone $start_day;
if ($display == 'month') {
$next->modify('+1 month');
} else if ($display == 'day') {
$next->modify('+7 day');
}
$display_start = $start_day->format('U');
$display_end = $next->format('U');
$start_of_week = $viewer->getUserSetting(
PhabricatorWeekStartDaySetting::SETTINGKEY);
$end_of_week = ($start_of_week + 6) % 7;
$first_of_month = $start_day->format('w');
$last_of_month = id(clone $next)->modify('-1 day')->format('w');
if (!$min_range || ($min_range < $display_start)) {
$min_range = $display_start;
if ($display == 'month' &&
$first_of_month !== $start_of_week) {
$interim_day_num = ($first_of_month + 7 - $start_of_week) % 7;
$min_range = id(clone $start_day)
->modify('-'.$interim_day_num.' days')
->format('U');
}
}
if (!$max_range || ($max_range > $display_end)) {
$max_range = $display_end;
if ($display == 'month' &&
$last_of_month !== $end_of_week) {
$interim_day_num = ($end_of_week + 7 - $last_of_month) % 7;
$max_range = id(clone $next)
->modify('+'.$interim_day_num.' days')
->format('U');
}
}
}
if ($upcoming) {
$now = PhabricatorTime::getNow();
if ($min_range) {
$min_range = max($now, $min_range);
} else {
$min_range = $now;
}
}
return array($min_range, $max_range);
}
protected function getURI($path) {
return '/calendar/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'month' => pht('Month View'),
'day' => pht('Day View'),
'upcoming' => pht('Upcoming Events'),
'all' => pht('All Events'),
);
return $names;
}
public function setCalendarYearAndMonthAndDay($year, $month, $day = null) {
$this->calendarYear = $year;
$this->calendarMonth = $month;
$this->calendarDay = $day;
return $this;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'month':
return $query->setParameter('display', 'month');
case 'day':
return $query->setParameter('display', 'day');
case 'upcoming':
return $query
->setParameter('display', 'list')
->setParameter('upcoming', array(
0 => 'upcoming',
));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $events,
PhabricatorSavedQuery $query,
array $handles) {
if ($this->isMonthView($query)) {
$result = $this->buildCalendarMonthView($events, $query);
} else if ($this->isDayView($query)) {
$result = $this->buildCalendarDayView($events, $query);
} else {
$result = $this->buildCalendarListView($events, $query);
}
return $result;
}
private function buildCalendarListView(
array $events,
PhabricatorSavedQuery $query) {
assert_instances_of($events, 'PhabricatorCalendarEvent');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($events as $event) {
if ($event->getIsGhostEvent()) {
$monogram = $event->getParentEvent()->getMonogram();
$index = $event->getSequenceIndex();
$monogram = "{$monogram}/{$index}";
} else {
$monogram = $event->getMonogram();
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($event)
->setObjectName($monogram)
->setHeader($event->getName())
->setHref($event->getURI());
$item->addAttribute($event->renderEventDate($viewer, false));
if ($event->getIsCancelled()) {
$item->setDisabled(true);
}
$status_icon = $event->getDisplayIcon($viewer);
$status_color = $event->getDisplayIconColor($viewer);
$status_label = $event->getDisplayIconLabel($viewer);
$item->setStatusIcon("{$status_icon} {$status_color}", $status_label);
$host = pht(
'Hosted by %s',
$viewer->renderHandle($event->getHostPHID()));
$item->addByline($host);
$list->addItem($item);
}
return $this->newResultView()
->setObjectList($list)
->setNoDataString(pht('No events found.'));
}
private function buildCalendarMonthView(
array $events,
PhabricatorSavedQuery $query) {
assert_instances_of($events, 'PhabricatorCalendarEvent');
$viewer = $this->requireViewer();
$now = PhabricatorTime::getNow();
list($start_year, $start_month) =
$this->getDisplayYearAndMonthAndDay(
$this->getQueryDateFrom($query)->getEpoch(),
$this->getQueryDateTo($query)->getEpoch(),
$query->getParameter('display'));
$now_year = phabricator_format_local_time($now, $viewer, 'Y');
$now_month = phabricator_format_local_time($now, $viewer, 'm');
$now_day = phabricator_format_local_time($now, $viewer, 'j');
if ($start_month == $now_month && $start_year == $now_year) {
$month_view = new PHUICalendarMonthView(
$this->getQueryDateFrom($query),
$this->getQueryDateTo($query),
$start_month,
$start_year,
$now_day);
} else {
$month_view = new PHUICalendarMonthView(
$this->getQueryDateFrom($query),
$this->getQueryDateTo($query),
$start_month,
$start_year);
}
$month_view->setUser($viewer);
$viewer_phid = $viewer->getPHID();
foreach ($events as $event) {
$epoch_min = $event->getStartDateTimeEpoch();
$epoch_max = $event->getEndDateTimeEpoch();
$is_invited = $event->isRSVPInvited($viewer_phid);
$is_attending = $event->getIsUserAttending($viewer_phid);
$event_view = id(new AphrontCalendarEventView())
->setHostPHID($event->getHostPHID())
->setEpochRange($epoch_min, $epoch_max)
->setIsCancelled($event->getIsCancelled())
->setName($event->getName())
->setURI($event->getURI())
->setIsAllDay($event->getIsAllDay())
->setIcon($event->getDisplayIcon($viewer))
->setViewerIsInvited($is_invited || $is_attending)
->setDatetimeSummary($event->renderEventDate($viewer, true))
->setIconColor($event->getDisplayIconColor($viewer));
$month_view->addEvent($event_view);
}
$month_view->setBrowseURI(
$this->getURI('query/'.$query->getQueryKey().'/'));
$from = $this->getQueryDateFrom($query)->getDateTime();
$crumbs = array();
$crumbs[] = id(new PHUICrumbView())
->setName($from->format('F Y'));
$header = id(new PHUIHeaderView())
->setProfileHeader(true)
->setHeader($from->format('F Y'));
return $this->newResultView($month_view)
->setCrumbs($crumbs)
->setHeader($header);
}
private function buildCalendarDayView(
array $events,
PhabricatorSavedQuery $query) {
$viewer = $this->requireViewer();
list($start_year, $start_month, $start_day) =
$this->getDisplayYearAndMonthAndDay(
$this->getQueryDateFrom($query)->getEpoch(),
$this->getQueryDateTo($query)->getEpoch(),
$query->getParameter('display'));
$day_view = id(new PHUICalendarDayView(
$this->getQueryDateFrom($query),
$this->getQueryDateTo($query),
$start_year,
$start_month,
$start_day))
->setQuery($query->getQueryKey());
$day_view->setUser($viewer);
$phids = mpull($events, 'getHostPHID');
foreach ($events as $event) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$event,
PhabricatorPolicyCapability::CAN_EDIT);
$epoch_min = $event->getStartDateTimeEpoch();
$epoch_max = $event->getEndDateTimeEpoch();
$status_icon = $event->getDisplayIcon($viewer);
$status_color = $event->getDisplayIconColor($viewer);
$event_view = id(new AphrontCalendarEventView())
->setCanEdit($can_edit)
->setEventID($event->getID())
->setEpochRange($epoch_min, $epoch_max)
->setIsAllDay($event->getIsAllDay())
->setIcon($status_icon)
->setIconColor($status_color)
->setName($event->getName())
->setURI($event->getURI())
->setDatetimeSummary($event->renderEventDate($viewer, true))
->setIsCancelled($event->getIsCancelled());
$day_view->addEvent($event_view);
}
$browse_uri = $this->getURI('query/'.$query->getQueryKey().'/');
$day_view->setBrowseURI($browse_uri);
$from = $this->getQueryDateFrom($query)->getDateTime();
$month_uri = $browse_uri.$from->format('Y/m/');
$crumbs = array(
id(new PHUICrumbView())
->setName($from->format('F Y'))
->setHref($month_uri),
id(new PHUICrumbView())
->setName($from->format('D jS')),
);
$header = id(new PHUIHeaderView())
->setProfileHeader(true)
->setHeader($from->format('D, F jS'));
return $this->newResultView($day_view)
->setCrumbs($crumbs)
->setHeader($header);
}
private function getDisplayYearAndMonthAndDay(
$range_start,
$range_end,
$display) {
$viewer = $this->requireViewer();
$epoch = null;
if ($this->calendarYear && $this->calendarMonth) {
$start_year = $this->calendarYear;
$start_month = $this->calendarMonth;
$start_day = $this->calendarDay ? $this->calendarDay : 1;
} else {
if ($range_start) {
$epoch = $range_start;
} else if ($range_end) {
$epoch = $range_end;
} else {
$epoch = time();
}
if ($display == 'month') {
$day = 1;
} else {
$day = phabricator_format_local_time($epoch, $viewer, 'd');
}
$start_year = phabricator_format_local_time($epoch, $viewer, 'Y');
$start_month = phabricator_format_local_time($epoch, $viewer, 'm');
$start_day = $day;
}
return array($start_year, $start_month, $start_day);
}
public function getPageSize(PhabricatorSavedQuery $saved) {
if ($this->isMonthView($saved) || $this->isDayView($saved)) {
return $saved->getParameter('limit', 1000);
} else {
return $saved->getParameter('limit', 100);
}
}
private function getQueryDateFrom(PhabricatorSavedQuery $saved) {
if ($this->calendarYear && $this->calendarMonth) {
$viewer = $this->requireViewer();
$start_year = $this->calendarYear;
$start_month = $this->calendarMonth;
$start_day = $this->calendarDay ? $this->calendarDay : 1;
return AphrontFormDateControlValue::newFromDictionary(
$viewer,
array(
'd' => "{$start_year}-{$start_month}-{$start_day}",
));
}
return $this->getQueryDate($saved, 'rangeStart');
}
private function getQueryDateTo(PhabricatorSavedQuery $saved) {
return $this->getQueryDate($saved, 'rangeEnd');
}
private function getQueryDate(PhabricatorSavedQuery $saved, $key) {
$viewer = $this->requireViewer();
$wild = $saved->getParameter($key);
return $this->getSafeDate($wild);
}
private function getSafeDate($value) {
$viewer = $this->requireViewer();
if ($value) {
// ideally this would be consistent and always pass in the same type
if ($value instanceof AphrontFormDateControlValue) {
return $value;
} else {
$value = AphrontFormDateControlValue::newFromWild($viewer, $value);
}
} else {
$value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
PhabricatorTime::getTodayMidnightDateTime($viewer)->format('U'));
$value->setEnabled(false);
}
$value->setOptional(true);
return $value;
}
private function isMonthView(PhabricatorSavedQuery $query) {
if ($this->isDayView($query)) {
return false;
}
if ($query->getParameter('display') == 'month') {
return true;
}
}
private function isDayView(PhabricatorSavedQuery $query) {
if ($query->getParameter('display') == 'day') {
return true;
}
if ($this->calendarDay) {
return true;
}
return false;
}
public function newUseResultsActions(PhabricatorSavedQuery $saved) {
$viewer = $this->requireViewer();
$can_export = $viewer->isLoggedIn();
return array(
id(new PhabricatorActionView())
->setIcon('fa-download')
->setName(pht('Export Query as .ics'))
->setDisabled(!$can_export)
->setHref('/calendar/export/edit/?queryKey='.$saved->getQueryKey()),
);
}
private function newResultView($content = null) {
// If we aren't rendering a dashboard panel, activate global drag-and-drop
// so you can import ".ics" files by dropping them directly onto the
// calendar.
if (!$this->isPanelContext()) {
$drop_upload = id(new PhabricatorGlobalUploadTargetView())
->setViewer($this->requireViewer())
->setHintText("\xE2\x87\xAA ".pht('Drop .ics Files to Import'))
->setSubmitURI('/calendar/import/drop/')
->setViewPolicy(PhabricatorPolicies::POLICY_NOONE);
$content = array(
$drop_upload,
$content,
);
}
return id(new PhabricatorApplicationSearchResultView())
->setContent($content);
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportQuery.php b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
index 7ef970216f..ecb2788459 100644
--- a/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExportQuery.php
@@ -1,90 +1,90 @@
<?php
final class PhabricatorCalendarExportQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $secretKeys;
private $isDisabled;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withIsDisabled($is_disabled) {
$this->isDisabled = $is_disabled;
return $this;
}
public function withSecretKeys(array $keys) {
$this->secretKeys = $keys;
return $this;
}
public function newResultObject() {
return new PhabricatorCalendarExport();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'export.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'export.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'export.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->isDisabled !== null) {
$where[] = qsprintf(
$conn,
'export.isDisabled = %d',
(int)$this->isDisabled);
}
if ($this->secretKeys !== null) {
$where[] = qsprintf(
$conn,
'export.secretKey IN (%Ls)',
$this->secretKeys);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'export';
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
index 032cab0c02..c718374da2 100644
--- a/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExportSearchEngine.php
@@ -1,123 +1,123 @@
<?php
final class PhabricatorCalendarExportSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Calendar Exports');
}
public function getApplicationClassName() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
$viewer = $this->requireViewer();
return id(new PhabricatorCalendarExportQuery())
->withAuthorPHIDs(array($viewer->getPHID()));
}
protected function buildCustomSearchFields() {
return array();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function getURI($path) {
return '/calendar/export/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Exports'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $exports,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($exports, 'PhabricatorCalendarExport');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($exports as $export) {
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
->setObjectName(pht('Export %d', $export->getID()))
->setHeader($export->getName())
->setHref($export->getURI());
if ($export->getIsDisabled()) {
$item->setDisabled(true);
}
$mode = $export->getPolicyMode();
$policy_icon = PhabricatorCalendarExport::getPolicyModeIcon($mode);
$policy_name = PhabricatorCalendarExport::getPolicyModeName($mode);
$policy_color = PhabricatorCalendarExport::getPolicyModeColor($mode);
$item->addIcon(
"{$policy_icon} {$policy_color}",
$policy_name);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No exports found.'));
return $result;
}
protected function getNewUserBody() {
$doc_name = 'Calendar User Guide: Exporting Events';
$doc_href = PhabricatorEnv::getDoclink($doc_name);
$create_button = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-book white')
->setText($doc_name)
->setHref($doc_href)
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon('fa-download')
->setTitle(pht('No Exports Configured'))
->setDescription(
pht(
'You have not set up any events for export from Calendar yet. '.
'See the documentation for instructions on how to get started.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php b/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
index 35891cfd28..f5d8f1eb32 100644
--- a/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php
@@ -1,64 +1,64 @@
<?php
final class PhabricatorCalendarExternalInviteeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function newResultObject() {
return new PhabricatorCalendarExternalInvitee();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->names !== null) {
$name_indexes = array();
foreach ($this->names as $name) {
$name_indexes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn,
'nameIndex IN (%Ls)',
$name_indexes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
index 731b1209cc..cd71c0f463 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportLogQuery.php
@@ -1,107 +1,107 @@
<?php
final class PhabricatorCalendarImportLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $importPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withImportPHIDs(array $phids) {
$this->importPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorCalendarImportLog();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'log.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'log.phid IN (%Ls)',
$this->phids);
}
if ($this->importPHIDs !== null) {
$where[] = qsprintf(
$conn,
'log.importPHID IN (%Ls)',
$this->importPHIDs);
}
return $where;
}
protected function willFilterPage(array $page) {
$viewer = $this->getViewer();
$type_map = PhabricatorCalendarImportLogType::getAllLogTypes();
foreach ($page as $log) {
$type_constant = $log->getParameter('type');
$type_object = idx($type_map, $type_constant);
if (!$type_object) {
$type_object = new PhabricatorCalendarImportDefaultLogType();
}
$type_object = clone $type_object;
$log->attachLogType($type_object);
}
$import_phids = mpull($page, 'getImportPHID');
if ($import_phids) {
$imports = id(new PhabricatorCalendarImportQuery())
->setViewer($viewer)
->withPHIDs($import_phids)
->execute();
$imports = mpull($imports, null, 'getPHID');
} else {
$imports = array();
}
foreach ($page as $key => $log) {
$import = idx($imports, $log->getImportPHID());
if (!$import) {
$this->didRejectResult($import);
unset($page[$key]);
continue;
}
$log->attachImport($import);
}
return $page;
}
protected function getPrimaryTableAlias() {
return 'log';
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportLogSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarImportLogSearchEngine.php
index 99f292f9a8..fd6896c37d 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportLogSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportLogSearchEngine.php
@@ -1,81 +1,81 @@
<?php
final class PhabricatorCalendarImportLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Calendar Import Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return new PhabricatorCalendarImportLogQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Import Sources'))
->setKey('importSourcePHIDs')
->setAliases(array('importSourcePHID')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['importSourcePHIDs']) {
$query->withImportPHIDs($map['importSourcePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/calendar/import/log/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Logs'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($logs, 'PhabricatorCalendarImportLog');
$viewer = $this->requireViewer();
$view = id(new PhabricatorCalendarImportLogView())
->setShowImportSources(true)
->setViewer($viewer)
->setLogs($logs);
return id(new PhabricatorApplicationSearchResultView())
->setTable($view->newTable());
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportQuery.php b/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
index 0e3dbbf387..7a3f12895f 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhabricatorCalendarImportQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $isDisabled;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withIsDisabled($is_disabled) {
$this->isDisabled = $is_disabled;
return $this;
}
public function newResultObject() {
return new PhabricatorCalendarImport();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'import.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'import.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'import.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->isDisabled !== null) {
$where[] = qsprintf(
$conn,
'import.isDisabled = %d',
(int)$this->isDisabled);
}
return $where;
}
protected function willFilterPage(array $page) {
$engines = PhabricatorCalendarImportEngine::getAllImportEngines();
foreach ($page as $key => $import) {
$engine_type = $import->getEngineType();
$engine = idx($engines, $engine_type);
if (!$engine) {
unset($page[$key]);
$this->didRejectResult($import);
continue;
}
$import->attachEngine(clone $engine);
}
return $page;
}
protected function getPrimaryTableAlias() {
return 'import';
}
public function getQueryApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarImportSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarImportSearchEngine.php
index a5e44812ea..509b1224e6 100644
--- a/src/applications/calendar/query/PhabricatorCalendarImportSearchEngine.php
+++ b/src/applications/calendar/query/PhabricatorCalendarImportSearchEngine.php
@@ -1,85 +1,85 @@
<?php
final class PhabricatorCalendarImportSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Calendar Imports');
}
public function getApplicationClassName() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return new PhabricatorCalendarImportQuery();
}
protected function buildCustomSearchFields() {
return array();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function getURI($path) {
return '/calendar/import/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Imports'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $imports,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($imports, 'PhabricatorCalendarImport');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($imports as $import) {
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
->setObjectName(pht('Import %d', $import->getID()))
->setHeader($import->getDisplayName())
->setHref($import->getURI());
if ($import->getIsDisabled()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No imports found.'));
return $result;
}
}
diff --git a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeDatasource.php b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeDatasource.php
index 987f9cbf09..7e8271fa92 100644
--- a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeDatasource.php
+++ b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeDatasource.php
@@ -1,53 +1,53 @@
<?php
final class PhabricatorCalendarInviteeDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Invitees');
}
public function getPlaceholderText() {
return pht('Type a user or project name, or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorCalendarInviteeUserDatasource(),
new PhabricatorCalendarInviteeViewerFunctionDatasource(),
new DifferentialExactUserFunctionDatasource(),
new PhabricatorProjectDatasource(),
);
}
public static function expandInvitees(
PhabricatorUser $viewer,
array $values) {
$phids = array();
foreach ($values as $value) {
if (phid_get_type($value) == PhabricatorPeopleUserPHIDType::TYPECONST) {
$phids[] = $value;
}
}
if (!$phids) {
return $values;
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs($phids)
->execute();
foreach ($projects as $project) {
$values[] = $project->getPHID();
}
return $values;
}
}
diff --git a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeUserDatasource.php b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeUserDatasource.php
index c799602d8a..0f834252ca 100644
--- a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeUserDatasource.php
+++ b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeUserDatasource.php
@@ -1,30 +1,30 @@
<?php
final class PhabricatorCalendarInviteeUserDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Users');
}
public function getPlaceholderText() {
return pht('Type a user name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorCalendarApplication';
+ return PhabricatorCalendarApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
protected function evaluateValues(array $values) {
return PhabricatorCalendarInviteeDatasource::expandInvitees(
$this->getViewer(),
$values);
}
}
diff --git a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeViewerFunctionDatasource.php b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeViewerFunctionDatasource.php
index 6f9a8292f4..d653c9bdea 100644
--- a/src/applications/calendar/typeahead/PhabricatorCalendarInviteeViewerFunctionDatasource.php
+++ b/src/applications/calendar/typeahead/PhabricatorCalendarInviteeViewerFunctionDatasource.php
@@ -1,77 +1,77 @@
<?php
final class PhabricatorCalendarInviteeViewerFunctionDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Viewer');
}
public function getPlaceholderText() {
return pht('Type viewer()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'viewer' => array(
'name' => pht('Current Viewer'),
'summary' => pht('Use the current viewing user.'),
'description' => pht(
'Show invites the current viewer is invited to. This function '.
'includes events the user is invited to because a project they '.
'are a member of is invited.'),
),
);
}
public function loadResults() {
if ($this->getViewer()->getPHID()) {
$results = array($this->renderViewerFunctionToken());
} else {
$results = array();
}
return $this->filterResultsAgainstTokens($results);
}
protected function canEvaluateFunction($function) {
if (!$this->getViewer()->getPHID()) {
return false;
}
return parent::canEvaluateFunction($function);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = $this->getViewer()->getPHID();
}
return PhabricatorCalendarInviteeDatasource::expandInvitees(
$this->getViewer(),
$results);
}
public function renderFunctionTokens($function, array $argv_list) {
$tokens = array();
foreach ($argv_list as $argv) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->renderViewerFunctionToken());
}
return $tokens;
}
private function renderViewerFunctionToken() {
return $this->newFunctionResult()
->setName(pht('Current Viewer'))
->setPHID('viewer()')
->setIcon('fa-user')
->setUnique(true);
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitLogQuery.php b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
index 19cb31a812..d9dcad695a 100644
--- a/src/applications/conduit/query/PhabricatorConduitLogQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
@@ -1,113 +1,113 @@
<?php
final class PhabricatorConduitLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $callerPHIDs;
private $methods;
private $methodStatuses;
private $epochMin;
private $epochMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withCallerPHIDs(array $phids) {
$this->callerPHIDs = $phids;
return $this;
}
public function withMethods(array $methods) {
$this->methods = $methods;
return $this;
}
public function withMethodStatuses(array $statuses) {
$this->methodStatuses = $statuses;
return $this;
}
public function withEpochBetween($epoch_min, $epoch_max) {
$this->epochMin = $epoch_min;
$this->epochMax = $epoch_max;
return $this;
}
public function newResultObject() {
return new PhabricatorConduitMethodCallLog();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->callerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'callerPHID IN (%Ls)',
$this->callerPHIDs);
}
if ($this->methods !== null) {
$where[] = qsprintf(
$conn,
'method IN (%Ls)',
$this->methods);
}
if ($this->methodStatuses !== null) {
$statuses = array_fuse($this->methodStatuses);
$methods = id(new PhabricatorConduitMethodQuery())
->setViewer($this->getViewer())
->execute();
$method_names = array();
foreach ($methods as $method) {
$status = $method->getMethodStatus();
if (isset($statuses[$status])) {
$method_names[] = $method->getAPIMethodName();
}
}
if (!$method_names) {
throw new PhabricatorEmptyQueryException();
}
$where[] = qsprintf(
$conn,
'method IN (%Ls)',
$method_names);
}
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'dateCreated >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'dateCreated <= %d',
$this->epochMax);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorConduitApplication';
+ return PhabricatorConduitApplication::class;
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php b/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php
index ab86ae6669..9e5e05b7b6 100644
--- a/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php
+++ b/src/applications/conduit/query/PhabricatorConduitLogSearchEngine.php
@@ -1,276 +1,276 @@
<?php
final class PhabricatorConduitLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Conduit Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorConduitApplication';
+ return PhabricatorConduitApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return new PhabricatorConduitLogQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['callerPHIDs']) {
$query->withCallerPHIDs($map['callerPHIDs']);
}
if ($map['methods']) {
$query->withMethods($map['methods']);
}
if ($map['statuses']) {
$query->withMethodStatuses($map['statuses']);
}
if ($map['epochMin'] || $map['epochMax']) {
$query->withEpochBetween(
$map['epochMin'],
$map['epochMax']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setKey('callerPHIDs')
->setLabel(pht('Callers'))
->setAliases(array('caller', 'callers'))
->setDescription(pht('Find calls by specific users.')),
id(new PhabricatorSearchStringListField())
->setKey('methods')
->setLabel(pht('Methods'))
->setDescription(pht('Find calls to specific methods.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Method Status'))
->setAliases(array('status'))
->setDescription(
pht('Find calls to stable, unstable, or deprecated methods.'))
->setOptions(ConduitAPIMethod::getMethodStatusMap()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Called After'))
->setKey('epochMin'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Called Before'))
->setKey('epochMax'),
);
}
protected function getURI($path) {
return '/conduit/log/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$viewer = $this->requireViewer();
if ($viewer->isLoggedIn()) {
$names['viewer'] = pht('My Calls');
$names['viewerdeprecated'] = pht('My Deprecated Calls');
}
$names['all'] = pht('All Call Logs');
$names['deprecated'] = pht('Deprecated Call Logs');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
$viewer_phid = $viewer->getPHID();
$deprecated = array(
ConduitAPIMethod::METHOD_STATUS_DEPRECATED,
);
switch ($query_key) {
case 'viewer':
return $query
->setParameter('callerPHIDs', array($viewer_phid));
case 'viewerdeprecated':
return $query
->setParameter('callerPHIDs', array($viewer_phid))
->setParameter('statuses', $deprecated);
case 'deprecated':
return $query
->setParameter('statuses', $deprecated);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function newExportFields() {
$viewer = $this->requireViewer();
return array(
id(new PhabricatorPHIDExportField())
->setKey('callerPHID')
->setLabel(pht('Caller PHID')),
id(new PhabricatorStringExportField())
->setKey('caller')
->setLabel(pht('Caller')),
id(new PhabricatorStringExportField())
->setKey('method')
->setLabel(pht('Method')),
id(new PhabricatorIntExportField())
->setKey('duration')
->setLabel(pht('Call Duration (us)')),
id(new PhabricatorStringExportField())
->setKey('error')
->setLabel(pht('Error')),
);
}
protected function newExportData(array $logs) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($logs as $log) {
if ($log->getCallerPHID()) {
$phids[] = $log->getCallerPHID();
}
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($logs as $log) {
$caller_phid = $log->getCallerPHID();
if ($caller_phid) {
$caller_name = $handles[$caller_phid]->getName();
} else {
$caller_name = null;
}
$map = array(
'callerPHID' => $caller_phid,
'caller' => $caller_name,
'method' => $log->getMethod(),
'duration' => (int)$log->getDuration(),
'error' => $log->getError(),
);
$export[] = $map;
}
return $export;
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($logs, 'PhabricatorConduitMethodCallLog');
$viewer = $this->requireViewer();
$methods = id(new PhabricatorConduitMethodQuery())
->setViewer($viewer)
->execute();
$methods = mpull($methods, null, 'getAPIMethodName');
Javelin::initBehavior('phabricator-tooltips');
$viewer = $this->requireViewer();
$rows = array();
foreach ($logs as $log) {
$caller_phid = $log->getCallerPHID();
if ($caller_phid) {
$caller = $viewer->renderHandle($caller_phid);
} else {
$caller = null;
}
$method = idx($methods, $log->getMethod());
if ($method) {
$method_status = $method->getMethodStatus();
} else {
$method_status = null;
}
switch ($method_status) {
case ConduitAPIMethod::METHOD_STATUS_STABLE:
$status = null;
break;
case ConduitAPIMethod::METHOD_STATUS_UNSTABLE:
$status = id(new PHUIIconView())
->setIcon('fa-exclamation-triangle yellow')
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Unstable'),
));
break;
case ConduitAPIMethod::METHOD_STATUS_DEPRECATED:
$status = id(new PHUIIconView())
->setIcon('fa-exclamation-triangle red')
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Deprecated'),
));
break;
default:
$status = id(new PHUIIconView())
->setIcon('fa-question-circle')
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Unknown ("%s")', $method_status),
));
break;
}
$rows[] = array(
$status,
$log->getMethod(),
$caller,
$log->getError(),
pht('%s us', new PhutilNumber($log->getDuration())),
phabricator_datetime($log->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
null,
pht('Method'),
pht('Caller'),
pht('Error'),
pht('Duration'),
pht('Date'),
))
->setColumnClasses(
array(
null,
'pri',
null,
'wide right',
null,
null,
));
return id(new PhabricatorApplicationSearchResultView())
->setTable($table)
->setNoDataString(pht('No matching calls in log.'));
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitMethodQuery.php b/src/applications/conduit/query/PhabricatorConduitMethodQuery.php
index eb61d8c480..5e68850d5f 100644
--- a/src/applications/conduit/query/PhabricatorConduitMethodQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitMethodQuery.php
@@ -1,158 +1,158 @@
<?php
final class PhabricatorConduitMethodQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $isDeprecated;
private $isStable;
private $isUnstable;
private $applicationNames;
private $nameContains;
private $methods;
private $isInternal;
public function withMethods(array $methods) {
$this->methods = $methods;
return $this;
}
public function withNameContains($name_contains) {
$this->nameContains = $name_contains;
return $this;
}
public function withIsStable($is_stable) {
$this->isStable = $is_stable;
return $this;
}
public function withIsUnstable($is_unstable) {
$this->isUnstable = $is_unstable;
return $this;
}
public function withIsDeprecated($is_deprecated) {
$this->isDeprecated = $is_deprecated;
return $this;
}
public function withIsInternal($is_internal) {
$this->isInternal = $is_internal;
return $this;
}
protected function loadPage() {
$methods = $this->getAllMethods();
$methods = $this->filterMethods($methods);
return $methods;
}
private function getAllMethods() {
return id(new PhutilClassMapQuery())
->setAncestorClass('ConduitAPIMethod')
->setSortMethod('getSortOrder')
->execute();
}
private function filterMethods(array $methods) {
foreach ($methods as $key => $method) {
$application = $method->getApplication();
if (!$application) {
continue;
}
if (!$application->isInstalled()) {
unset($methods[$key]);
}
}
$status = array(
ConduitAPIMethod::METHOD_STATUS_STABLE => $this->isStable,
ConduitAPIMethod::METHOD_STATUS_FROZEN => $this->isStable,
ConduitAPIMethod::METHOD_STATUS_DEPRECATED => $this->isDeprecated,
ConduitAPIMethod::METHOD_STATUS_UNSTABLE => $this->isUnstable,
);
// Only apply status filters if any of them are set.
if (array_filter($status)) {
foreach ($methods as $key => $method) {
$keep = idx($status, $method->getMethodStatus());
if (!$keep) {
unset($methods[$key]);
}
}
}
if ($this->nameContains) {
$needle = phutil_utf8_strtolower($this->nameContains);
foreach ($methods as $key => $method) {
$haystack = $method->getAPIMethodName();
$haystack = phutil_utf8_strtolower($haystack);
if (strpos($haystack, $needle) === false) {
unset($methods[$key]);
}
}
}
if ($this->methods) {
$map = array_fuse($this->methods);
foreach ($methods as $key => $method) {
$needle = $method->getAPIMethodName();
if (empty($map[$needle])) {
unset($methods[$key]);
}
}
}
if ($this->isInternal !== null) {
foreach ($methods as $key => $method) {
if ($method->isInternalAPI() !== $this->isInternal) {
unset($methods[$key]);
}
}
}
return $methods;
}
protected function willFilterPage(array $methods) {
$application_phids = array();
foreach ($methods as $method) {
$application = $method->getApplication();
if ($application === null) {
continue;
}
$application_phids[] = $application->getPHID();
}
if ($application_phids) {
$applications = id(new PhabricatorApplicationQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($application_phids)
->execute();
$applications = mpull($applications, null, 'getPHID');
} else {
$applications = array();
}
// Remove methods which belong to an application the viewer can not see.
foreach ($methods as $key => $method) {
$application = $method->getApplication();
if ($application === null) {
continue;
}
if (empty($applications[$application->getPHID()])) {
$this->didRejectResult($method);
unset($methods[$key]);
}
}
return $methods;
}
public function getQueryApplicationClass() {
- return 'PhabricatorConduitApplication';
+ return PhabricatorConduitApplication::class;
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitSearchEngine.php b/src/applications/conduit/query/PhabricatorConduitSearchEngine.php
index 3dc5617bb5..2fd95c3550 100644
--- a/src/applications/conduit/query/PhabricatorConduitSearchEngine.php
+++ b/src/applications/conduit/query/PhabricatorConduitSearchEngine.php
@@ -1,192 +1,192 @@
<?php
final class PhabricatorConduitSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Conduit Methods');
}
public function getApplicationClassName() {
- return 'PhabricatorConduitApplication';
+ return PhabricatorConduitApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function getPageSize(PhabricatorSavedQuery $saved) {
return PHP_INT_MAX - 1;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('isStable', $request->getStr('isStable'));
$saved->setParameter('isUnstable', $request->getStr('isUnstable'));
$saved->setParameter('isDeprecated', $request->getStr('isDeprecated'));
$saved->setParameter('nameContains', $request->getStr('nameContains'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorConduitMethodQuery());
$query->withIsStable($saved->getParameter('isStable'));
$query->withIsUnstable($saved->getParameter('isUnstable'));
$query->withIsDeprecated($saved->getParameter('isDeprecated'));
$query->withIsInternal(false);
$contains = $saved->getParameter('nameContains');
if (phutil_nonempty_string($contains)) {
$query->withNameContains($contains);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$form
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name Contains'))
->setName('nameContains')
->setValue($saved->getParameter('nameContains')));
$is_stable = $saved->getParameter('isStable');
$is_unstable = $saved->getParameter('isUnstable');
$is_deprecated = $saved->getParameter('isDeprecated');
$form
->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel('Stability')
->addCheckbox(
'isStable',
1,
hsprintf(
'<strong>%s</strong>: %s',
pht('Stable Methods'),
pht('Show established API methods with stable interfaces.')),
$is_stable)
->addCheckbox(
'isUnstable',
1,
hsprintf(
'<strong>%s</strong>: %s',
pht('Unstable Methods'),
pht('Show new methods which are subject to change.')),
$is_unstable)
->addCheckbox(
'isDeprecated',
1,
hsprintf(
'<strong>%s</strong>: %s',
pht('Deprecated Methods'),
pht(
'Show old methods which will be deleted in a future '.
'version of this software.')),
$is_deprecated));
}
protected function getURI($path) {
return '/conduit/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'modern' => pht('Modern Methods'),
'all' => pht('All Methods'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'modern':
return $query
->setParameter('isStable', true)
->setParameter('isUnstable', true);
case 'all':
return $query
->setParameter('isStable', true)
->setParameter('isUnstable', true)
->setParameter('isDeprecated', true);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $methods,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($methods, 'ConduitAPIMethod');
$viewer = $this->requireViewer();
$out = array();
$last = null;
$list = null;
foreach ($methods as $method) {
$app = $method->getApplicationName();
if ($app !== $last) {
$last = $app;
if ($list) {
$out[] = $list;
}
$list = id(new PHUIObjectItemListView());
$list->setHeader($app);
$app_object = $method->getApplication();
if ($app_object) {
$app_name = $app_object->getName();
} else {
$app_name = $app;
}
}
$method_name = $method->getAPIMethodName();
$item = id(new PHUIObjectItemView())
->setHeader($method_name)
->setHref($this->getApplicationURI('method/'.$method_name.'/'))
->addAttribute($method->getMethodSummary());
switch ($method->getMethodStatus()) {
case ConduitAPIMethod::METHOD_STATUS_STABLE:
break;
case ConduitAPIMethod::METHOD_STATUS_UNSTABLE:
$item->addIcon('fa-warning', pht('Unstable'));
$item->setStatusIcon('fa-warning yellow');
break;
case ConduitAPIMethod::METHOD_STATUS_DEPRECATED:
$item->addIcon('fa-warning', pht('Deprecated'));
$item->setStatusIcon('fa-warning red');
break;
case ConduitAPIMethod::METHOD_STATUS_FROZEN:
$item->addIcon('fa-archive', pht('Frozen'));
$item->setStatusIcon('fa-archive grey');
break;
}
$list->addItem($item);
}
if ($list) {
$out[] = $list;
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($out);
return $result;
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
index 384efccadf..0f3f581513 100644
--- a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
@@ -1,115 +1,115 @@
<?php
final class PhabricatorConduitTokenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
private $expired;
private $tokens;
private $tokenTypes;
public function withExpired($expired) {
$this->expired = $expired;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function withTokens(array $tokens) {
$this->tokens = $tokens;
return $this;
}
public function withTokenTypes(array $types) {
$this->tokenTypes = $types;
return $this;
}
public function newResultObject() {
return new PhabricatorConduitToken();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->tokens !== null) {
$where[] = qsprintf(
$conn,
'token IN (%Ls)',
$this->tokens);
}
if ($this->tokenTypes !== null) {
$where[] = qsprintf(
$conn,
'tokenType IN (%Ls)',
$this->tokenTypes);
}
if ($this->expired !== null) {
if ($this->expired) {
$where[] = qsprintf(
$conn,
'expires <= %d',
PhabricatorTime::getNow());
} else {
$where[] = qsprintf(
$conn,
'expires IS NULL OR expires > %d',
PhabricatorTime::getNow());
}
}
return $where;
}
protected function willFilterPage(array $tokens) {
$object_phids = mpull($tokens, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($tokens as $key => $token) {
$object = idx($objects, $token->getObjectPHID(), null);
if (!$object) {
$this->didRejectResult($token);
unset($tokens[$key]);
continue;
}
$token->attachObject($object);
}
return $tokens;
}
public function getQueryApplicationClass() {
- return 'PhabricatorConduitApplication';
+ return PhabricatorConduitApplication::class;
}
}
diff --git a/src/applications/config/editor/PhabricatorConfigEditor.php b/src/applications/config/editor/PhabricatorConfigEditor.php
index 7a8833c84e..4eb8838d3e 100644
--- a/src/applications/config/editor/PhabricatorConfigEditor.php
+++ b/src/applications/config/editor/PhabricatorConfigEditor.php
@@ -1,165 +1,165 @@
<?php
final class PhabricatorConfigEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorConfigApplication';
+ return PhabricatorConfigApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Configuration');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorConfigTransaction::TYPE_EDIT;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorConfigTransaction::TYPE_EDIT:
return array(
'deleted' => (int)$object->getIsDeleted(),
'value' => $object->getValue(),
);
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorConfigTransaction::TYPE_EDIT:
return $xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorConfigTransaction::TYPE_EDIT:
$v = $xaction->getNewValue();
// If this is a defined configuration option (vs a straggler from an
// old version of Phabricator or a configuration file misspelling)
// submit it to the validation gauntlet.
$key = $object->getConfigKey();
$all_options = PhabricatorApplicationConfigOptions::loadAllOptions();
$option = idx($all_options, $key);
if ($option) {
$option->getGroup()->validateOption(
$option,
$v['value']);
}
$object->setIsDeleted((int)$v['deleted']);
$object->setValue($v['value']);
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$type = $u->getTransactionType();
switch ($type) {
case PhabricatorConfigTransaction::TYPE_EDIT:
return $v;
}
return parent::mergeTransactions($u, $v);
}
protected function transactionHasEffect(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$type = $xaction->getTransactionType();
switch ($type) {
case PhabricatorConfigTransaction::TYPE_EDIT:
// If an edit deletes an already-deleted entry, no-op it.
if (idx($old, 'deleted') && idx($new, 'deleted')) {
return false;
}
break;
}
return parent::transactionHasEffect($object, $xaction);
}
protected function didApplyTransactions($object, array $xactions) {
// Force all the setup checks to run on the next page load.
PhabricatorSetupCheck::deleteSetupCheckCache();
return $xactions;
}
public static function storeNewValue(
PhabricatorUser $user,
PhabricatorConfigEntry $config_entry,
$value,
PhabricatorContentSource $source,
$acting_as_phid = null) {
$xaction = id(new PhabricatorConfigTransaction())
->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT)
->setNewValue(
array(
'deleted' => false,
'value' => $value,
));
$editor = id(new PhabricatorConfigEditor())
->setActor($user)
->setContinueOnNoEffect(true)
->setContentSource($source);
if ($acting_as_phid) {
$editor->setActingAsPHID($acting_as_phid);
}
$editor->applyTransactions($config_entry, array($xaction));
}
public static function deleteConfig(
PhabricatorUser $user,
PhabricatorConfigEntry $config_entry,
PhabricatorContentSource $source) {
$xaction = id(new PhabricatorConfigTransaction())
->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT)
->setNewValue(
array(
'deleted' => true,
'value' => null,
));
$editor = id(new PhabricatorConfigEditor())
->setActor($user)
->setContinueOnNoEffect(true)
->setContentSource($source);
$editor->applyTransactions($config_entry, array($xaction));
}
}
diff --git a/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php b/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php
index 95c543427f..fb72a18257 100644
--- a/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php
+++ b/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhabricatorConfigConfigPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CONF';
public function getTypeName() {
return pht('Config');
}
public function newObject() {
return new PhabricatorConfigEntry();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorConfigApplication';
+ return PhabricatorConfigApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorConfigEntryQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$entry = $objects[$phid];
$key = $entry->getConfigKey();
$handle->setName($key);
$handle->setURI("/config/edit/{$key}/");
}
}
}
diff --git a/src/applications/config/query/PhabricatorConfigEntryQuery.php b/src/applications/config/query/PhabricatorConfigEntryQuery.php
index f46fdb7d1e..c228c2b7cc 100644
--- a/src/applications/config/query/PhabricatorConfigEntryQuery.php
+++ b/src/applications/config/query/PhabricatorConfigEntryQuery.php
@@ -1,60 +1,60 @@
<?php
final class PhabricatorConfigEntryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ids;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorConfigEntry();
$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);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorConfigApplication';
+ return PhabricatorConfigApplication::class;
}
}
diff --git a/src/applications/conpherence/editor/ConpherenceEditEngine.php b/src/applications/conpherence/editor/ConpherenceEditEngine.php
index f5f850e637..7b1b7d1aa4 100644
--- a/src/applications/conpherence/editor/ConpherenceEditEngine.php
+++ b/src/applications/conpherence/editor/ConpherenceEditEngine.php
@@ -1,118 +1,118 @@
<?php
final class ConpherenceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'conpherence.thread';
public function getEngineName() {
return pht('Conpherence');
}
public function getEngineApplicationClass() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Conpherence Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Conpherence.');
}
protected function newEditableObject() {
return ConpherenceThread::initializeNewRoom($this->getViewer());
}
protected function newObjectQuery() {
return new ConpherenceThreadQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Room');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Room: %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return $object->getTitle();
}
protected function getObjectCreateShortText() {
return pht('Create Room');
}
protected function getObjectName() {
return pht('Room');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
public function isEngineConfigurable() {
return false;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
if ($this->getIsCreate()) {
$participant_phids = array($viewer->getPHID());
$initial_phids = array();
} else {
$participant_phids = $object->getParticipantPHIDs();
$initial_phids = $participant_phids;
}
// Only show participants on create or conduit, not edit.
$show_participants = (bool)$this->getIsCreate();
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Room name.'))
->setConduitTypeDescription(pht('New Room name.'))
->setIsRequired(true)
->setTransactionType(
ConpherenceThreadTitleTransaction::TRANSACTIONTYPE)
->setValue($object->getTitle()),
id(new PhabricatorTextEditField())
->setKey('topic')
->setLabel(pht('Topic'))
->setDescription(pht('Room topic.'))
->setConduitTypeDescription(pht('New Room topic.'))
->setTransactionType(
ConpherenceThreadTopicTransaction::TRANSACTIONTYPE)
->setValue($object->getTopic()),
id(new PhabricatorUsersEditField())
->setKey('participants')
->setValue($participant_phids)
->setInitialValue($initial_phids)
->setIsFormField($show_participants)
->setAliases(array('users', 'members', 'participants', 'userPHID'))
->setDescription(pht('Room participants.'))
->setUseEdgeTransactions(true)
->setConduitTypeDescription(pht('New Room participants.'))
->setTransactionType(
ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE)
->setLabel(pht('Initial Participants')),
);
}
}
diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php
index a1d6431d8c..fe5d0a60ca 100644
--- a/src/applications/conpherence/editor/ConpherenceEditor.php
+++ b/src/applications/conpherence/editor/ConpherenceEditor.php
@@ -1,249 +1,249 @@
<?php
final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
const ERROR_EMPTY_PARTICIPANTS = 'error-empty-participants';
const ERROR_EMPTY_MESSAGE = 'error-empty-message';
public function getEditorApplicationClass() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Conpherence Rooms');
}
public static function createThread(
PhabricatorUser $creator,
array $participant_phids,
$title,
$message,
PhabricatorContentSource $source,
$topic) {
$conpherence = ConpherenceThread::initializeNewRoom($creator);
$errors = array();
if (empty($participant_phids)) {
$errors[] = self::ERROR_EMPTY_PARTICIPANTS;
} else {
$participant_phids[] = $creator->getPHID();
$participant_phids = array_unique($participant_phids);
}
if (empty($message)) {
$errors[] = self::ERROR_EMPTY_MESSAGE;
}
if (!$errors) {
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE)
->setNewValue(array('+' => $participant_phids));
if ($title) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTitleTransaction::TRANSACTIONTYPE)
->setNewValue($title);
}
if (strlen($topic)) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceThreadTopicTransaction::TRANSACTIONTYPE)
->setNewValue($topic);
}
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new ConpherenceTransactionComment())
->setContent($message)
->setConpherencePHID($conpherence->getPHID()));
id(new ConpherenceEditor())
->setActor($creator)
->setContentSource($source)
->setContinueOnNoEffect(true)
->applyTransactions($conpherence, $xactions);
}
return array($errors, $conpherence);
}
public function generateTransactionsFromText(
PhabricatorUser $viewer,
ConpherenceThread $conpherence,
$text) {
$xactions = array();
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new ConpherenceTransactionComment())
->setContent($text)
->setConpherencePHID($conpherence->getPHID()));
return $xactions;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this room.', $author);
}
protected function applyBuiltinInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$object->setMessageCount((int)$object->getMessageCount() + 1);
break;
}
return parent::applyBuiltinInternalTransaction($object, $xaction);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$acting_phid = $this->getActingAsPHID();
$participants = $object->getParticipants();
foreach ($participants as $participant) {
if ($participant->getParticipantPHID() == $acting_phid) {
$participant->markUpToDate($object);
}
}
if ($participants) {
PhabricatorUserCache::clearCaches(
PhabricatorUserMessageCountCacheType::KEY_COUNT,
array_keys($participants));
}
if ($xactions) {
$data = array(
'type' => 'message',
'threadPHID' => $object->getPHID(),
'messageID' => last($xactions)->getID(),
'subscribers' => array($object->getPHID()),
);
PhabricatorNotificationClient::tryToPostMessage($data);
}
return $xactions;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ConpherenceReplyHandler())
->setActor($this->getActor())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$title = $object->getTitle();
if (!$title) {
$title = pht(
'%s sent you a message.',
$this->getActor()->getUserName());
}
return id(new PhabricatorMetaMTAMail())
->setSubject("Z{$id}: {$title}");
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$to_phids = array();
$participants = $object->getParticipants();
if (!$participants) {
return $to_phids;
}
$participant_phids = mpull($participants, 'getParticipantPHID');
$users = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($participant_phids)
->needUserSettings(true)
->execute();
$users = mpull($users, null, 'getPHID');
$notification_key = PhabricatorConpherenceNotificationsSetting::SETTINGKEY;
$notification_email =
PhabricatorConpherenceNotificationsSetting::VALUE_CONPHERENCE_EMAIL;
foreach ($participants as $phid => $participant) {
$user = idx($users, $phid);
if ($user) {
$default = $user->getUserSetting($notification_key);
} else {
$default = $notification_email;
}
$settings = $participant->getSettings();
$notifications = idx($settings, 'notifications', $default);
if ($notifications == $notification_email) {
$to_phids[] = $phid;
}
}
return $to_phids;
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('CONPHERENCE DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function addEmailPreferenceSectionToMailBody(
PhabricatorMetaMTAMailBody $body,
PhabricatorLiskDAO $object,
array $xactions) {
$href = PhabricatorEnv::getProductionURI(
'/'.$object->getMonogram().'?settings');
$label = pht('EMAIL PREFERENCES FOR THIS ROOM');
$body->addLinkSection($label, $href);
}
protected function getMailSubjectPrefix() {
return pht('[Conpherence]');
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php b/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php
index 98f0d74797..d8273b6d6e 100644
--- a/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php
+++ b/src/applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorConpherenceThreadPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CONP';
public function getTypeName() {
return pht('Conpherence Room');
}
public function newObject() {
return new ConpherenceThread();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ConpherenceThreadQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$thread = $objects[$phid];
$title = $thread->getStaticTitle();
$monogram = $thread->getMonogram();
$handle->setName($title);
$handle->setFullName(pht('%s: %s', $monogram, $title));
$handle->setURI('/'.$monogram);
}
}
public function canLoadNamedObject($name) {
return preg_match('/^Z\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new ConpherenceThreadQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$objects = mpull($objects, null, 'getID');
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php
index 34bbf7e6b0..72986d0c22 100644
--- a/src/applications/conpherence/query/ConpherenceThreadQuery.php
+++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php
@@ -1,345 +1,345 @@
<?php
final class ConpherenceThreadQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const TRANSACTION_LIMIT = 100;
private $phids;
private $ids;
private $participantPHIDs;
private $needParticipants;
private $needTransactions;
private $afterTransactionID;
private $beforeTransactionID;
private $transactionLimit;
private $fulltext;
private $needProfileImage;
public function needParticipants($need) {
$this->needParticipants = $need;
return $this;
}
public function needProfileImage($need) {
$this->needProfileImage = $need;
return $this;
}
public function needTransactions($need_transactions) {
$this->needTransactions = $need_transactions;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withParticipantPHIDs(array $phids) {
$this->participantPHIDs = $phids;
return $this;
}
public function setAfterTransactionID($id) {
$this->afterTransactionID = $id;
return $this;
}
public function setBeforeTransactionID($id) {
$this->beforeTransactionID = $id;
return $this;
}
public function setTransactionLimit($transaction_limit) {
$this->transactionLimit = $transaction_limit;
return $this;
}
public function getTransactionLimit() {
return $this->transactionLimit;
}
public function withFulltext($query) {
$this->fulltext = $query;
return $this;
}
public function withTitleNgrams($ngrams) {
return $this->withNgramsConstraint(
id(new ConpherenceThreadTitleNgrams()),
$ngrams);
}
protected function loadPage() {
$table = new ConpherenceThread();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT thread.* FROM %T thread %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$conpherences = $table->loadAllFromArray($data);
if ($conpherences) {
$conpherences = mpull($conpherences, null, 'getPHID');
$this->loadParticipantsAndInitHandles($conpherences);
if ($this->needParticipants) {
$this->loadCoreHandles($conpherences, 'getParticipantPHIDs');
}
if ($this->needTransactions) {
$this->loadTransactionsAndHandles($conpherences);
}
if ($this->needProfileImage) {
$default = null;
$file_phids = mpull($conpherences, 'getProfileImagePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($conpherences as $conpherence) {
$file = idx($files, $conpherence->getProfileImagePHID());
if (!$file) {
if (!$default) {
$default = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'conpherence.png');
}
$file = $default;
}
$conpherence->attachProfileImageFile($file);
}
}
}
return $conpherences;
}
protected function buildGroupClause(AphrontDatabaseConnection $conn_r) {
if ($this->participantPHIDs !== null ||
phutil_nonempty_string($this->fulltext)) {
return qsprintf($conn_r, 'GROUP BY thread.id');
} else {
return $this->buildApplicationSearchGroupClause($conn_r);
}
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->participantPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T p ON p.conpherencePHID = thread.phid',
id(new ConpherenceParticipant())->getTableName());
}
if (phutil_nonempty_string($this->fulltext)) {
$joins[] = qsprintf(
$conn,
'JOIN %T idx ON idx.threadPHID = thread.phid',
id(new ConpherenceIndex())->getTableName());
}
// See note in buildWhereClauseParts() about this optimization.
$viewer = $this->getViewer();
if (!$viewer->isOmnipotent() && $viewer->isLoggedIn()) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T vp ON vp.conpherencePHID = thread.phid
AND vp.participantPHID = %s',
id(new ConpherenceParticipant())->getTableName(),
$viewer->getPHID());
}
return $joins;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
// Optimize policy filtering of private rooms. If we are not looking for
// particular rooms by ID or PHID, we can just skip over any rooms with
// "View Policy: Room Participants" if the viewer isn't a participant: we
// know they won't be able to see the room.
// This avoids overheating browse/search queries, since it's common for
// a large number of rooms to be private and have this view policy.
$viewer = $this->getViewer();
$can_optimize =
!$viewer->isOmnipotent() &&
($this->ids === null) &&
($this->phids === null);
if ($can_optimize) {
$members_policy = id(new ConpherenceThreadMembersPolicyRule())
->getObjectPolicyFullKey();
$policies = array(
$members_policy,
PhabricatorPolicies::POLICY_USER,
PhabricatorPolicies::POLICY_ADMIN,
PhabricatorPolicies::POLICY_NOONE,
);
if ($viewer->isLoggedIn()) {
$where[] = qsprintf(
$conn,
'thread.viewPolicy NOT IN (%Ls) OR vp.participantPHID = %s',
$policies,
$viewer->getPHID());
} else {
$where[] = qsprintf(
$conn,
'thread.viewPolicy NOT IN (%Ls)',
$policies);
}
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'thread.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'thread.phid IN (%Ls)',
$this->phids);
}
if ($this->participantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'p.participantPHID IN (%Ls)',
$this->participantPHIDs);
}
if (phutil_nonempty_string($this->fulltext)) {
$where[] = qsprintf(
$conn,
'MATCH(idx.corpus) AGAINST (%s IN BOOLEAN MODE)',
$this->fulltext);
}
return $where;
}
private function loadParticipantsAndInitHandles(array $conpherences) {
$participants = id(new ConpherenceParticipant())
->loadAllWhere('conpherencePHID IN (%Ls)', array_keys($conpherences));
$map = mgroup($participants, 'getConpherencePHID');
foreach ($conpherences as $current_conpherence) {
$conpherence_phid = $current_conpherence->getPHID();
$conpherence_participants = idx(
$map,
$conpherence_phid,
array());
$conpherence_participants = mpull(
$conpherence_participants,
null,
'getParticipantPHID');
$current_conpherence->attachParticipants($conpherence_participants);
$current_conpherence->attachHandles(array());
}
return $this;
}
private function loadCoreHandles(
array $conpherences,
$method) {
$handle_phids = array();
foreach ($conpherences as $conpherence) {
$handle_phids[$conpherence->getPHID()] =
$conpherence->$method();
}
$flat_phids = array_mergev($handle_phids);
$viewer = $this->getViewer();
$handles = $viewer->loadHandles($flat_phids);
$handles = iterator_to_array($handles);
foreach ($handle_phids as $conpherence_phid => $phids) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachHandles(
$conpherence->getHandles() + array_select_keys($handles, $phids));
}
return $this;
}
private function loadTransactionsAndHandles(array $conpherences) {
// NOTE: This is older code which has been modernized to the minimum
// standard required by T13266. It probably isn't the best available
// approach to the problems it solves.
$limit = $this->getTransactionLimit();
if ($limit) {
// fetch an extra for "show older" scenarios
$limit = $limit + 1;
} else {
$limit = 0xFFFF;
}
$pager = id(new AphrontCursorPagerView())
->setPageSize($limit);
// We have to flip these for the underlying query class. The semantics of
// paging are tricky business.
if ($this->afterTransactionID) {
$pager->setBeforeID($this->afterTransactionID);
} else if ($this->beforeTransactionID) {
$pager->setAfterID($this->beforeTransactionID);
}
$transactions = id(new ConpherenceTransactionQuery())
->setViewer($this->getViewer())
->withObjectPHIDs(array_keys($conpherences))
->needHandles(true)
->executeWithCursorPager($pager);
$transactions = mgroup($transactions, 'getObjectPHID');
foreach ($conpherences as $phid => $conpherence) {
$current_transactions = idx($transactions, $phid, array());
$handles = array();
foreach ($current_transactions as $transaction) {
$handles += $transaction->getHandles();
}
$conpherence->attachHandles($conpherence->getHandles() + $handles);
$conpherence->attachTransactions($current_transactions);
}
return $this;
}
public function getQueryApplicationClass() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
protected function getPrimaryTableAlias() {
return 'thread';
}
}
diff --git a/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php
index 77e54157cf..505d7c4a0e 100644
--- a/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php
+++ b/src/applications/conpherence/query/ConpherenceThreadSearchEngine.php
@@ -1,445 +1,445 @@
<?php
final class ConpherenceThreadSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Conpherence Rooms');
}
public function getApplicationClassName() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
public function newQuery() {
return id(new ConpherenceThreadQuery())
->needProfileImage(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Participants'))
->setKey('participants')
->setAliases(array('participant')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Rooms'))
->setKey('phids')
->setDescription(pht('Search by room titles.'))
->setDatasource(id(new ConpherenceThreadDatasource())),
id(new PhabricatorSearchTextField())
->setLabel(pht('Room Contains Words'))
->setKey('fulltext'),
);
}
protected function getDefaultFieldOrder() {
return array(
'participants',
'...',
);
}
protected function shouldShowOrderField() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['participants']) {
$query->withParticipantPHIDs($map['participants']);
}
if ($map['fulltext']) {
$query->withFulltext($map['fulltext']);
}
if ($map['phids']) {
$query->withPHIDs($map['phids']);
}
return $query;
}
protected function getURI($path) {
return '/conpherence/search/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All Rooms');
if ($this->requireViewer()->isLoggedIn()) {
$names['participant'] = pht('Joined Rooms');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'participant':
return $query->setParameter(
'participants',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $conpherences,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($conpherences, 'ConpherenceThread');
$viewer = $this->requireViewer();
$policy_objects = ConpherenceThread::loadViewPolicyObjects(
$viewer,
$conpherences);
$engines = array();
$fulltext = $query->getParameter('fulltext');
if (phutil_nonempty_string($fulltext) && $conpherences) {
$context = $this->loadContextMessages($conpherences, $fulltext);
$author_phids = array();
foreach ($context as $phid => $messages) {
$conpherence = $conpherences[$phid];
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer)
->setContextObject($conpherence);
foreach ($messages as $group) {
foreach ($group as $message) {
$xaction = $message['xaction'];
if ($xaction) {
$author_phids[] = $xaction->getAuthorPHID();
$engine->addObject(
$xaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
}
$engine->process();
$engines[$phid] = $engine;
}
$handles = $viewer->loadHandles($author_phids);
$handles = iterator_to_array($handles);
} else {
$context = array();
}
$content = array();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($conpherences as $conpherence_phid => $conpherence) {
$created = phabricator_date($conpherence->getDateCreated(), $viewer);
$title = $conpherence->getTitle();
$monogram = $conpherence->getMonogram();
$icon_name = $conpherence->getPolicyIconName($policy_objects);
$icon = id(new PHUIIconView())
->setIcon($icon_name);
if (!strlen($fulltext)) {
$item = id(new PHUIObjectItemView())
->setObjectName($conpherence->getMonogram())
->setHeader($title)
->setHref('/'.$conpherence->getMonogram())
->setObject($conpherence)
->setImageURI($conpherence->getProfileImageURI())
->addIcon('none', $created)
->addIcon(
'none',
pht('Messages: %d', $conpherence->getMessageCount()))
->addAttribute(
array(
$icon,
' ',
pht(
'Last updated %s',
phabricator_datetime($conpherence->getDateModified(), $viewer)),
));
$list->addItem($item);
} else {
$messages = idx($context, $conpherence_phid);
$box = array();
$list = null;
if ($messages) {
foreach ($messages as $group) {
$rows = array();
foreach ($group as $message) {
$xaction = $message['xaction'];
if (!$xaction) {
continue;
}
$view = id(new ConpherenceTransactionView())
->setUser($viewer)
->setHandles($handles)
->setMarkupEngine($engines[$conpherence_phid])
->setConpherenceThread($conpherence)
->setConpherenceTransaction($xaction)
->setSearchResult(true)
->addClass('conpherence-fulltext-result');
if ($message['match']) {
$view->addClass('conpherence-fulltext-match');
}
$rows[] = $view;
}
$box[] = id(new PHUIBoxView())
->appendChild($rows)
->addClass('conpherence-fulltext-results');
}
}
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon($icon_name)
->setHref('/'.$monogram);
$content[] = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($box);
}
}
if ($list) {
$content = $list;
} else {
$content = id(new PHUIBoxView())
->addClass('conpherence-search-room-results')
->appendChild($content);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($content);
$result->setNoDataString(pht('No results found.'));
return $result;
}
private function loadContextMessages(array $threads, $fulltext) {
$phids = mpull($threads, 'getPHID');
// We want to load a few messages for each thread in the result list, to
// show some of the actual content hits to help the user find what they
// are looking for.
// This method is trying to batch this lookup in most cases, so we do
// between one and "a handful" of queries instead of one per thread in
// most cases. To do this:
//
// - Load a big block of results for all of the threads.
// - If we didn't get a full block back, we have everything that matches
// the query. Sort it out and exit.
// - Otherwise, some threads had a ton of hits, so we might not be
// getting everything we want (we could be getting back 1,000 hits for
// the first thread). Remove any threads which we have enough results
// for and try again.
// - Repeat until we have everything or every thread has enough results.
//
// In the worst case, we could end up degrading to one query per thread,
// but this is incredibly unlikely on real data.
// Size of the result blocks we're going to load.
$limit = 1000;
// Number of messages we want for each thread.
$want = 3;
$need = $phids;
$hits = array();
while ($need) {
$rows = id(new ConpherenceFulltextQuery())
->withThreadPHIDs($need)
->withFulltext($fulltext)
->setLimit($limit)
->execute();
foreach ($rows as $row) {
$hits[$row['threadPHID']][] = $row;
}
if (count($rows) < $limit) {
break;
}
foreach ($need as $key => $phid) {
if (count($hits[$phid]) >= $want) {
unset($need[$key]);
}
}
}
// Now that we have all the fulltext matches, throw away any extras that we
// aren't going to render so we don't need to do lookups on them.
foreach ($hits as $phid => $rows) {
if (count($rows) > $want) {
$hits[$phid] = array_slice($rows, 0, $want);
}
}
// For each fulltext match, we want to render a message before and after
// the match to give it some context. We already know the transactions
// before each match because the rows have a "previousTransactionPHID",
// but we need to do one more query to figure out the transactions after
// each match.
// Collect the transactions we want to find the next transactions for.
$after = array();
foreach ($hits as $phid => $rows) {
foreach ($rows as $row) {
$after[] = $row['transactionPHID'];
}
}
// Look up the next transactions.
if ($after) {
$after_rows = id(new ConpherenceFulltextQuery())
->withPreviousTransactionPHIDs($after)
->execute();
} else {
$after_rows = array();
}
// Build maps from PHIDs to the previous and next PHIDs.
$prev_map = array();
$next_map = array();
foreach ($after_rows as $row) {
$next_map[$row['previousTransactionPHID']] = $row['transactionPHID'];
}
foreach ($hits as $phid => $rows) {
foreach ($rows as $row) {
$prev = $row['previousTransactionPHID'];
if ($prev) {
$prev_map[$row['transactionPHID']] = $prev;
$next_map[$prev] = $row['transactionPHID'];
}
}
}
// Now we're going to collect the actual transaction PHIDs, in order, that
// we want to show for each thread.
$groups = array();
foreach ($hits as $thread_phid => $rows) {
$rows = ipull($rows, null, 'transactionPHID');
$done = array();
foreach ($rows as $phid => $row) {
if (isset($done[$phid])) {
continue;
}
$done[$phid] = true;
$group = array();
// Walk backward, finding all the previous results. We can just keep
// going until we run out of results because we've only loaded things
// that we want to show.
$prev = $phid;
while (true) {
if (!isset($prev_map[$prev])) {
// No previous transaction, so we're done.
break;
}
$prev = $prev_map[$prev];
if (isset($rows[$prev])) {
$match = true;
$done[$prev] = true;
} else {
$match = false;
}
$group[] = array(
'phid' => $prev,
'match' => $match,
);
}
if (count($group) > 1) {
$group = array_reverse($group);
}
$group[] = array(
'phid' => $phid,
'match' => true,
);
$next = $phid;
while (true) {
if (!isset($next_map[$next])) {
break;
}
$next = $next_map[$next];
if (isset($rows[$next])) {
$match = true;
$done[$next] = true;
} else {
$match = false;
}
$group[] = array(
'phid' => $next,
'match' => $match,
);
}
$groups[$thread_phid][] = $group;
}
}
// Load all the actual transactions we need.
$xaction_phids = array();
foreach ($groups as $thread_phid => $group) {
foreach ($group as $list) {
foreach ($list as $item) {
$xaction_phids[] = $item['phid'];
}
}
}
if ($xaction_phids) {
$xactions = id(new ConpherenceTransactionQuery())
->setViewer($this->requireViewer())
->withPHIDs($xaction_phids)
->needComments(true)
->execute();
$xactions = mpull($xactions, null, 'getPHID');
} else {
$xactions = array();
}
foreach ($groups as $thread_phid => $group) {
foreach ($group as $key => $list) {
foreach ($list as $lkey => $item) {
$xaction = idx($xactions, $item['phid']);
if ($xaction->shouldHide()) {
continue;
}
$groups[$thread_phid][$key][$lkey]['xaction'] = $xaction;
}
}
}
// TODO: Sort the groups chronologically?
return $groups;
}
}
diff --git a/src/applications/conpherence/typeahead/ConpherenceThreadDatasource.php b/src/applications/conpherence/typeahead/ConpherenceThreadDatasource.php
index a18b4a73ea..735769a0cc 100644
--- a/src/applications/conpherence/typeahead/ConpherenceThreadDatasource.php
+++ b/src/applications/conpherence/typeahead/ConpherenceThreadDatasource.php
@@ -1,47 +1,47 @@
<?php
final class ConpherenceThreadDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Room');
}
public function getPlaceholderText() {
return pht('Type a room title...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorConpherenceApplication';
+ return PhabricatorConpherenceApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$rooms = id(new ConpherenceThreadQuery())
->setViewer($viewer)
->withTitleNgrams($raw_query)
->needParticipants(true)
->execute();
$results = array();
foreach ($rooms as $room) {
if (strlen($room->getTopic())) {
$topic = $room->getTopic();
} else {
$topic = phutil_tag('em', array(), pht('No topic set'));
}
$token = id(new PhabricatorTypeaheadResult())
->setName($room->getTitle())
->setPHID($room->getPHID())
->addAttribute($topic);
$results[] = $token;
}
return $results;
}
}
diff --git a/src/applications/countdown/editor/PhabricatorCountdownEditEngine.php b/src/applications/countdown/editor/PhabricatorCountdownEditEngine.php
index 4f67339ac5..003f448be9 100644
--- a/src/applications/countdown/editor/PhabricatorCountdownEditEngine.php
+++ b/src/applications/countdown/editor/PhabricatorCountdownEditEngine.php
@@ -1,116 +1,116 @@
<?php
final class PhabricatorCountdownEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'countdown.countdown';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Countdowns');
}
public function getSummaryHeader() {
return pht('Edit Countdowns');
}
public function getSummaryText() {
return pht('Creates and edits countdowns.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorCountdownApplication';
+ return PhabricatorCountdownApplication::class;
}
protected function newEditableObject() {
return PhabricatorCountdown::initializeNewCountdown(
$this->getViewer());
}
protected function newObjectQuery() {
return id(new PhabricatorCountdownQuery());
}
protected function getObjectCreateTitleText($object) {
return pht('Create Countdown');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Countdown');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Countdown: %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return pht('Edit Countdown');
}
protected function getObjectCreateShortText() {
return pht('Create Countdown');
}
protected function getObjectName() {
return pht('Countdown');
}
protected function getCommentViewHeaderText($object) {
return pht('Last Words');
}
protected function getCommentViewButtonText($object) {
return pht('Contemplate Infinity');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorCountdownCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$epoch_value = $object->getEpoch();
if ($epoch_value === null) {
$epoch_value = PhabricatorTime::getNow();
}
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setIsRequired(true)
->setTransactionType(
PhabricatorCountdownTitleTransaction::TRANSACTIONTYPE)
->setDescription(pht('The countdown name.'))
->setConduitDescription(pht('Rename the countdown.'))
->setConduitTypeDescription(pht('New countdown name.'))
->setValue($object->getTitle()),
id(new PhabricatorEpochEditField())
->setKey('epoch')
->setLabel(pht('End Date'))
->setTransactionType(
PhabricatorCountdownEpochTransaction::TRANSACTIONTYPE)
->setDescription(pht('Date when the countdown ends.'))
->setConduitDescription(pht('Change the end date of the countdown.'))
->setConduitTypeDescription(pht('New countdown end date.'))
->setValue($epoch_value),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setTransactionType(
PhabricatorCountdownDescriptionTransaction::TRANSACTIONTYPE)
->setDescription(pht('Description of the countdown.'))
->setConduitDescription(pht('Change the countdown description.'))
->setConduitTypeDescription(pht('New description.'))
->setValue($object->getDescription()),
);
}
}
diff --git a/src/applications/countdown/editor/PhabricatorCountdownEditor.php b/src/applications/countdown/editor/PhabricatorCountdownEditor.php
index 2102b3785b..1037320902 100644
--- a/src/applications/countdown/editor/PhabricatorCountdownEditor.php
+++ b/src/applications/countdown/editor/PhabricatorCountdownEditor.php
@@ -1,96 +1,96 @@
<?php
final class PhabricatorCountdownEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorCountdownApplication';
+ return PhabricatorCountdownApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Countdown');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_SPACE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
PhabricatorCountdownTransaction::MAILTAG_DETAILS =>
pht('Someone changes the countdown details.'),
PhabricatorCountdownTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a countdown.'),
PhabricatorCountdownTransaction::MAILTAG_OTHER =>
pht('Other countdown activity not listed above occurs.'),
);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$description = $object->getDescription();
if (strlen($description)) {
$body->addRemarkupSection(
pht('COUNTDOWN DESCRIPTION'),
$object->getDescription());
}
$body->addLinkSection(
pht('COUNTDOWN DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function getMailSubjectPrefix() {
return '[Countdown]';
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorCountdownReplyHandler())
->setMailReceiver($object);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php b/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php
index 7e6278c8ea..f72ecb4808 100644
--- a/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php
+++ b/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorCountdownCountdownPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CDWN';
public function getTypeName() {
return pht('Countdown');
}
public function newObject() {
return new PhabricatorCountdown();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorCountdownApplication';
+ return PhabricatorCountdownApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCountdownQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$countdown = $objects[$phid];
$name = $countdown->getTitle();
$id = $countdown->getID();
$handle->setName($countdown->getMonogram());
$handle->setFullName(pht('%s: %s', $countdown->getMonogram(), $name));
$handle->setURI($countdown->getURI());
}
}
public function canLoadNamedObject($name) {
return preg_match('/^C\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorCountdownQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/countdown/query/PhabricatorCountdownQuery.php b/src/applications/countdown/query/PhabricatorCountdownQuery.php
index 4a6df16e8e..51360c52de 100644
--- a/src/applications/countdown/query/PhabricatorCountdownQuery.php
+++ b/src/applications/countdown/query/PhabricatorCountdownQuery.php
@@ -1,103 +1,103 @@
<?php
final class PhabricatorCountdownQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $upcoming;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withUpcoming() {
$this->upcoming = true;
return $this;
}
public function newResultObject() {
return new PhabricatorCountdown();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'authorPHID in (%Ls)',
$this->authorPHIDs);
}
if ($this->upcoming !== null) {
$where[] = qsprintf(
$conn,
'epoch >= %d',
PhabricatorTime::getNow());
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorCountdownApplication';
+ return PhabricatorCountdownApplication::class;
}
public function getBuiltinOrders() {
return array(
'ending' => array(
'vector' => array('-epoch', '-id'),
'name' => pht('End Date (Past to Future)'),
),
'unending' => array(
'vector' => array('epoch', 'id'),
'name' => pht('End Date (Future to Past)'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return array(
'epoch' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'epoch',
'type' => 'int',
),
) + parent::getOrderableColumns();
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'epoch' => (int)$object->getEpoch(),
);
}
}
diff --git a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php
index 2f9fe9c0e8..a0f93763c8 100644
--- a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php
+++ b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php
@@ -1,166 +1,166 @@
<?php
final class PhabricatorCountdownSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Countdowns');
}
public function getApplicationClassName() {
- return 'PhabricatorCountdownApplication';
+ return PhabricatorCountdownApplication::class;
}
public function newQuery() {
return new PhabricatorCountdownQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['upcoming'] && $map['upcoming'][0] == 'upcoming') {
$query->withUpcoming();
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors')),
id(new PhabricatorSearchCheckboxesField())
->setKey('upcoming')
->setOptions(
array(
'upcoming' => pht('Show only upcoming countdowns.'),
)),
);
}
protected function getURI($path) {
return '/countdown/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'upcoming' => pht('Upcoming'),
'all' => pht('All'),
);
if ($this->requireViewer()->getPHID()) {
$names['authored'] = pht('Authored');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
case 'upcoming':
return $query->setParameter('upcoming', array('upcoming'));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $countdowns,
PhabricatorSavedQuery $query) {
return mpull($countdowns, 'getAuthorPHID');
}
protected function renderResultList(
array $countdowns,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($countdowns, 'PhabricatorCountdown');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($countdowns as $countdown) {
$id = $countdown->getID();
$ended = false;
$epoch = $countdown->getEpoch();
if ($epoch <= PhabricatorTime::getNow()) {
$ended = true;
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($countdown)
->setObjectName($countdown->getMonogram())
->setHeader($countdown->getTitle())
->setHref($countdown->getURI())
->addByline(
pht(
'Created by %s',
$handles[$countdown->getAuthorPHID()]->renderLink()));
if ($ended) {
$item->addAttribute(
pht('Launched on %s', phabricator_datetime($epoch, $viewer)));
$item->setDisabled(true);
} else {
$time_left = ($epoch - PhabricatorTime::getNow());
$num = round($time_left / (60 * 60 * 24));
$noun = pht('Days');
if ($num < 1) {
$num = round($time_left / (60 * 60), 1);
$noun = pht('Hours');
}
$item->setCountdown($num, $noun);
$item->addAttribute(
phabricator_datetime($epoch, $viewer));
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No countdowns found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Countdown'))
->setHref('/countdown/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Keep track of upcoming launch dates with '.
'embeddable counters.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
index 2c5b6baa3b..a604ef4939 100644
--- a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
+++ b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
@@ -1,195 +1,195 @@
<?php
final class PhabricatorDaemonLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const STATUS_ALL = 'status-all';
const STATUS_ALIVE = 'status-alive';
const STATUS_RUNNING = 'status-running';
private $ids;
private $notIDs;
private $status = self::STATUS_ALL;
private $daemonClasses;
private $allowStatusWrites;
private $daemonIDs;
public static function getTimeUntilUnknown() {
return 3 * PhutilDaemonHandle::getHeartbeatEventFrequency();
}
public static function getTimeUntilDead() {
return 30 * PhutilDaemonHandle::getHeartbeatEventFrequency();
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withoutIDs(array $ids) {
$this->notIDs = $ids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withDaemonClasses(array $classes) {
$this->daemonClasses = $classes;
return $this;
}
public function setAllowStatusWrites($allow) {
$this->allowStatusWrites = $allow;
return $this;
}
public function withDaemonIDs(array $daemon_ids) {
$this->daemonIDs = $daemon_ids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorDaemonLog();
$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 willFilterPage(array $daemons) {
$unknown_delay = self::getTimeUntilUnknown();
$dead_delay = self::getTimeUntilDead();
$status_running = PhabricatorDaemonLog::STATUS_RUNNING;
$status_unknown = PhabricatorDaemonLog::STATUS_UNKNOWN;
$status_wait = PhabricatorDaemonLog::STATUS_WAIT;
$status_exiting = PhabricatorDaemonLog::STATUS_EXITING;
$status_exited = PhabricatorDaemonLog::STATUS_EXITED;
$status_dead = PhabricatorDaemonLog::STATUS_DEAD;
$filter = array_fuse($this->getStatusConstants());
foreach ($daemons as $key => $daemon) {
$status = $daemon->getStatus();
$seen = $daemon->getDateModified();
$is_running = ($status == $status_running) ||
($status == $status_wait) ||
($status == $status_exiting);
// If we haven't seen the daemon recently, downgrade its status to
// unknown.
$unknown_time = ($seen + $unknown_delay);
if ($is_running && ($unknown_time < time())) {
$status = $status_unknown;
}
// If the daemon hasn't been seen in quite a while, assume it is dead.
$dead_time = ($seen + $dead_delay);
if (($status == $status_unknown) && ($dead_time < time())) {
$status = $status_dead;
}
// If we changed the daemon's status, adjust it.
if ($status != $daemon->getStatus()) {
$daemon->setStatus($status);
// ...and write it, if we're in a context where that's reasonable.
if ($this->allowStatusWrites) {
$guard = AphrontWriteGuard::beginScopedUnguardedWrites();
$daemon->save();
unset($guard);
}
}
// If the daemon no longer matches the filter, get rid of it.
if ($filter) {
if (empty($filter[$daemon->getStatus()])) {
unset($daemons[$key]);
}
}
}
return $daemons;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->notIDs !== null) {
$where[] = qsprintf(
$conn,
'id NOT IN (%Ld)',
$this->notIDs);
}
if ($this->getStatusConstants()) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->getStatusConstants());
}
if ($this->daemonClasses !== null) {
$where[] = qsprintf(
$conn,
'daemon IN (%Ls)',
$this->daemonClasses);
}
if ($this->daemonIDs !== null) {
$where[] = qsprintf(
$conn,
'daemonID IN (%Ls)',
$this->daemonIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
private function getStatusConstants() {
$status = $this->status;
switch ($status) {
case self::STATUS_ALL:
return array();
case self::STATUS_RUNNING:
return array(
PhabricatorDaemonLog::STATUS_RUNNING,
);
case self::STATUS_ALIVE:
return array(
PhabricatorDaemonLog::STATUS_UNKNOWN,
PhabricatorDaemonLog::STATUS_RUNNING,
PhabricatorDaemonLog::STATUS_WAIT,
PhabricatorDaemonLog::STATUS_EXITING,
);
default:
throw new Exception(pht('Unknown status "%s"!', $status));
}
}
public function getQueryApplicationClass() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php
index 84b36fe546..cae823f868 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php
@@ -1,113 +1,113 @@
<?php
final class PhabricatorDashboardEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'dashboard';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Dashboards');
}
public function getSummaryHeader() {
return pht('Edit Dashboards');
}
public function getSummaryText() {
return pht('This engine is used to modify dashboards.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return PhabricatorDashboard::initializeNewDashboard($viewer);
}
protected function newObjectQuery() {
return new PhabricatorDashboardQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Dashboard');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Dashboard');
}
protected function getObjectCreateCancelURI($object) {
return '/dashboard/';
}
protected function getObjectEditTitleText($object) {
return pht('Edit Dashboard: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Dashboard');
}
protected function getObjectCreateShortText() {
return pht('Create Dashboard');
}
protected function getObjectName() {
return pht('Dashboard');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorDashboardCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$layout_options = PhabricatorDashboardLayoutMode::getLayoutModeMap();
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the dashboard.'))
->setConduitDescription(pht('Rename the dashboard.'))
->setConduitTypeDescription(pht('New dashboard name.'))
->setTransactionType(
PhabricatorDashboardNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorIconSetEditField())
->setKey('icon')
->setLabel(pht('Icon'))
->setTransactionType(
PhabricatorDashboardIconTransaction::TRANSACTIONTYPE)
->setIconSet(new PhabricatorDashboardIconSet())
->setDescription(pht('Dashboard icon.'))
->setConduitDescription(pht('Change the dashboard icon.'))
->setConduitTypeDescription(pht('New dashboard icon.'))
->setValue($object->getIcon()),
id(new PhabricatorSelectEditField())
->setKey('layout')
->setLabel(pht('Layout'))
->setDescription(pht('Dashboard layout mode.'))
->setConduitDescription(pht('Change the dashboard layout mode.'))
->setConduitTypeDescription(pht('New dashboard layout mode.'))
->setTransactionType(
PhabricatorDashboardLayoutTransaction::TRANSACTIONTYPE)
->setOptions($layout_options)
->setValue($object->getRawLayoutMode()),
);
return $fields;
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php
index 129f28b347..92c7dbdf1a 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php
@@ -1,204 +1,204 @@
<?php
final class PhabricatorDashboardPanelEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'dashboard.panel';
private $panelType;
private $contextObject;
private $columnKey;
public function setPanelType($panel_type) {
$this->panelType = $panel_type;
return $this;
}
public function getPanelType() {
return $this->panelType;
}
public function setContextObject($context) {
$this->contextObject = $context;
return $this;
}
public function getContextObject() {
return $this->contextObject;
}
public function setColumnKey($column_key) {
$this->columnKey = $column_key;
return $this;
}
public function getColumnKey() {
return $this->columnKey;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Dashboard Panels');
}
public function getSummaryHeader() {
return pht('Edit Dashboard Panels');
}
protected function supportsSearch() {
return true;
}
public function getSummaryText() {
return pht('This engine is used to modify dashboard panels.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$panel = PhabricatorDashboardPanel::initializeNewPanel($viewer);
if ($this->panelType) {
$panel->setPanelType($this->panelType);
}
return $panel;
}
protected function newEditableObjectForDocumentation() {
$panel = parent::newEditableObjectForDocumentation();
$text_type = id(new PhabricatorDashboardTextPanelType())
->getPanelTypeKey();
$panel->setPanelType($text_type);
return $panel;
}
protected function newObjectQuery() {
return new PhabricatorDashboardPanelQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Dashboard Panel');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Panel');
}
protected function getObjectCreateCancelURI($object) {
$context = $this->getContextObject();
if ($context) {
return $context->getURI();
}
return parent::getObjectCreateCancelURI($object);
}
public function getEffectiveObjectEditDoneURI($object) {
$context = $this->getContextObject();
if ($context) {
return $context->getURI();
}
return parent::getEffectiveObjectEditDoneURI($object);
}
protected function getObjectEditCancelURI($object) {
$context = $this->getContextObject();
if ($context) {
return $context->getURI();
}
return parent::getObjectEditCancelURI($object);
}
protected function getObjectEditTitleText($object) {
return pht('Edit Panel: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Panel');
}
protected function getObjectCreateShortText() {
return pht('Edit Panel');
}
protected function getObjectName() {
return pht('Dashboard Panel');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function didApplyTransactions($object, array $xactions) {
$context = $this->getContextObject();
if ($context instanceof PhabricatorDashboard) {
// Only add the panel to the dashboard when we're creating a new panel,
// not if we're editing an existing panel.
if (!$this->getIsCreate()) {
return;
}
$viewer = $this->getViewer();
$controller = $this->getController();
$request = $controller->getRequest();
$dashboard = $context;
$xactions = array();
$ref_list = clone $dashboard->getPanelRefList();
$ref_list->newPanelRef($object, $this->getColumnKey());
$new_panels = $ref_list->toDictionary();
$xactions[] = $dashboard->getApplicationTransactionTemplate()
->setTransactionType(
PhabricatorDashboardPanelsTransaction::TRANSACTIONTYPE)
->setNewValue($new_panels);
$editor = $dashboard->getApplicationTransactionEditor()
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
$editor->applyTransactions($dashboard, $xactions);
}
}
protected function buildCustomEditFields($object) {
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the panel.'))
->setConduitDescription(pht('Rename the panel.'))
->setConduitTypeDescription(pht('New panel name.'))
->setTransactionType(
PhabricatorDashboardPanelNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);
$panel_fields = $object->getEditEngineFields();
foreach ($panel_fields as $panel_field) {
$fields[] = $panel_field;
}
return $fields;
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
index ea03c1ac7d..6e6d2b618b 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
@@ -1,28 +1,28 @@
<?php
final class PhabricatorDashboardPanelTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Dashboard Panels');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPortalEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardPortalEditEngine.php
index 9945ea9d28..17880b5501 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardPortalEditEngine.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardPortalEditEngine.php
@@ -1,87 +1,87 @@
<?php
final class PhabricatorDashboardPortalEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'portal';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Portals');
}
public function getSummaryHeader() {
return pht('Edit Portals');
}
public function getSummaryText() {
return pht('This engine is used to modify portals.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function newEditableObject() {
return PhabricatorDashboardPortal::initializeNewPortal();
}
protected function newObjectQuery() {
return new PhabricatorDashboardPortalQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Portal');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Portal');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Portal: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Portal');
}
protected function getObjectCreateShortText() {
return pht('Create Portal');
}
protected function getObjectName() {
return pht('Portal');
}
protected function getObjectViewURI($object) {
if ($this->getIsCreate()) {
return $object->getURI();
} else {
return '/portal/view/'.$object->getID().'/view/manage/';
}
}
protected function getEditorURI() {
return '/portal/edit/';
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the portal.'))
->setConduitDescription(pht('Rename the portal.'))
->setConduitTypeDescription(pht('New portal name.'))
->setTransactionType(
PhabricatorDashboardPortalNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPortalEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardPortalEditor.php
index 2c8a3ccfac..ee2a2307ba 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardPortalEditor.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardPortalEditor.php
@@ -1,35 +1,35 @@
<?php
final class PhabricatorDashboardPortalEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Portals');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this portal.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
index 4a84577467..8964beab70 100644
--- a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
+++ b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
@@ -1,28 +1,28 @@
<?php
final class PhabricatorDashboardTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Dashboards');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php b/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php
index 1450e2aa68..0aae485b58 100644
--- a/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php
+++ b/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhabricatorDashboardDashboardPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DSHB';
public function getTypeName() {
return pht('Dashboard');
}
public function newObject() {
return new PhabricatorDashboard();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorDashboardQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$dashboard = $objects[$phid];
$id = $dashboard->getID();
$handle->setName($dashboard->getName());
$handle->setURI("/dashboard/view/{$id}/");
}
}
}
diff --git a/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php b/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php
index d84db72a25..1019740320 100644
--- a/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php
+++ b/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php
@@ -1,79 +1,79 @@
<?php
final class PhabricatorDashboardPanelPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DSHP';
public function getTypeName() {
return pht('Panel');
}
public function newObject() {
return new PhabricatorDashboardPanel();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorDashboardPanelQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$panel = $objects[$phid];
$name = $panel->getName();
$monogram = $panel->getMonogram();
$handle
->setIcon('fa-window-maximize')
->setName($name)
->setFullName("{$monogram} {$name}")
->setURI($panel->getURI());
if ($panel->getIsArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^W\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorDashboardPanelQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/dashboard/phid/PhabricatorDashboardPortalPHIDType.php b/src/applications/dashboard/phid/PhabricatorDashboardPortalPHIDType.php
index 378748d96b..3faad72924 100644
--- a/src/applications/dashboard/phid/PhabricatorDashboardPortalPHIDType.php
+++ b/src/applications/dashboard/phid/PhabricatorDashboardPortalPHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhabricatorDashboardPortalPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'PRTL';
public function getTypeName() {
return pht('Portal');
}
public function newObject() {
return new PhabricatorDashboardPortal();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorDashboardPortalQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$portal = $objects[$phid];
$handle
->setIcon('fa-compass')
->setName($portal->getName())
->setURI($portal->getURI());
}
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
index 54f627eb00..7ec76898b9 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
@@ -1,105 +1,105 @@
<?php
final class PhabricatorDashboardPanelQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $archived;
private $panelTypes;
private $authorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
/**
* Whether to get only the Archived (`true`), only the not
* Archived (`false`) or all (`null`). Default to `null` (no filter).
*
* @param null|bool $archived
* @return self
*/
public function withArchived($archived) {
$this->archived = $archived;
return $this;
}
public function withPanelTypes(array $types) {
$this->panelTypes = $types;
return $this;
}
public function withAuthorPHIDs(array $authors) {
$this->authorPHIDs = $authors;
return $this;
}
public function newResultObject() {
// TODO: If we don't do this, SearchEngine explodes when trying to
// enumerate custom fields. For now, just give the panel a default panel
// type so custom fields work. In the long run, we may want to find a
// cleaner or more general approach for this.
$text_type = id(new PhabricatorDashboardTextPanelType())
->getPanelTypeKey();
return id(new PhabricatorDashboardPanel())
->setPanelType($text_type);
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'panel.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'panel.phid IN (%Ls)',
$this->phids);
}
if ($this->archived !== null) {
$where[] = qsprintf(
$conn,
'panel.isArchived = %d',
(int)$this->archived);
}
if ($this->panelTypes !== null) {
$where[] = qsprintf(
$conn,
'panel.panelType IN (%Ls)',
$this->panelTypes);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'panel.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function getPrimaryTableAlias() {
return 'panel';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
index dc50fa5d66..be59345aaa 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php
@@ -1,150 +1,150 @@
<?php
final class PhabricatorDashboardPanelSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Dashboard Panels');
}
public function getApplicationClassName() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function newQuery() {
return new PhabricatorDashboardPanelQuery();
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['status']) {
switch ($map['status']) {
case 'active':
$query->withArchived(false);
break;
case 'archived':
$query->withArchived(true);
break;
default:
break;
}
}
if ($map['paneltype']) {
$query->withPanelTypes(array($map['paneltype']));
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Authored By'))
->setKey('authorPHIDs')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchSelectField())
->setKey('status')
->setLabel(pht('Status'))
->setOptions(
id(new PhabricatorDashboardPanel())
->getStatuses()),
id(new PhabricatorSearchSelectField())
->setKey('paneltype')
->setLabel(pht('Panel Type'))
->setOptions(
id(new PhabricatorDashboardPanel())
->getPanelTypes()),
);
}
protected function getURI($path) {
return '/dashboard/panel/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
$names['active'] = pht('Active Panels');
$names['all'] = pht('All Panels');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'active':
return $query->setParameter('status', 'active');
case 'authored':
return $query->setParameter(
'authorPHIDs',
array(
$viewer->getPHID(),
));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $panels,
PhabricatorSavedQuery $query,
array $handles) {
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($panels as $panel) {
$item = id(new PHUIObjectItemView())
->setObjectName($panel->getMonogram())
->setHeader($panel->getName())
->setHref('/'.$panel->getMonogram())
->setObject($panel);
$impl = $panel->getImplementation();
if ($impl) {
$type_text = $impl->getPanelTypeName();
} else {
$type_text = nonempty($panel->getPanelType(), pht('Unknown Type'));
}
$item->addAttribute($type_text);
$properties = $panel->getProperties();
$class = idx($properties, 'class');
$item->addAttribute($class);
if ($panel->getIsArchived()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No panels found.'));
return $result;
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
index 418262c745..9dd0da68e8 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPortalQuery.php
@@ -1,64 +1,64 @@
<?php
final class PhabricatorDashboardPortalQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhabricatorDashboardPortal();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'portal.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'portal.phid IN (%Ls)',
$this->phids);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'portal.status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function getPrimaryTableAlias() {
return 'portal';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPortalSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPortalSearchEngine.php
index c1633f2e97..b5ce3068b7 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPortalSearchEngine.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPortalSearchEngine.php
@@ -1,78 +1,78 @@
<?php
final class PhabricatorDashboardPortalSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Portals');
}
public function getApplicationClassName() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function newQuery() {
return new PhabricatorDashboardPortalQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getURI($path) {
return '/portal/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All Portals');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $portals,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($portals, 'PhabricatorDashboardPortal');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($portals as $portal) {
$item = id(new PHUIObjectItemView())
->setObjectName($portal->getObjectName())
->setHeader($portal->getName())
->setHref($portal->getURI())
->setObject($portal);
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No portals found.'));
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
index 954a565ac6..3078140e24 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
@@ -1,99 +1,99 @@
<?php
final class PhabricatorDashboardQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $authorPHIDs;
private $canEdit;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withAuthorPHIDs(array $authors) {
$this->authorPHIDs = $authors;
return $this;
}
public function withCanEdit($can_edit) {
$this->canEdit = $can_edit;
return $this;
}
public function newResultObject() {
return new PhabricatorDashboard();
}
protected function didFilterPage(array $dashboards) {
$phids = mpull($dashboards, 'getPHID');
if ($this->canEdit) {
$dashboards = id(new PhabricatorPolicyFilter())
->setViewer($this->getViewer())
->requireCapabilities(array(
PhabricatorPolicyCapability::CAN_EDIT,
))
->apply($dashboards);
}
return $dashboards;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'dashboard.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'dashboard.phid IN (%Ls)',
$this->phids);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'dashboard.status IN (%Ls)',
$this->statuses);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'dashboard.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
protected function getPrimaryTableAlias() {
return 'dashboard';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
index ea3f69faab..c02778c77d 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
@@ -1,176 +1,176 @@
<?php
final class PhabricatorDashboardSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Dashboards');
}
public function getApplicationClassName() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function newQuery() {
return id(new PhabricatorDashboardQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Authored By'))
->setKey('authorPHIDs')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(PhabricatorDashboard::getStatusNameMap()),
id(new PhabricatorSearchCheckboxesField())
->setKey('editable')
->setLabel(pht('Editable'))
->setOptions(array('editable' => null)),
);
}
protected function getURI($path) {
return '/dashboard/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
$names['open'] = pht('Active Dashboards');
$names['all'] = pht('All Dashboards');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array(
$viewer->getPHID(),
));
case 'open':
return $query->setParameter(
'statuses',
array(
PhabricatorDashboard::STATUS_ACTIVE,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['editable'] !== null) {
$query->withCanEdit($map['editable']);
}
return $query;
}
protected function renderResultList(
array $dashboards,
PhabricatorSavedQuery $query,
array $handles) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($dashboards as $dashboard) {
$author_phid = $dashboard->getAuthorPHID();
if ($author_phid) {
$phids[] = $author_phid;
}
}
$handles = $viewer->loadHandles($phids);
if ($dashboards) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($dashboards, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
}
$list = id(new PHUIObjectItemListView())
->setViewer($viewer);
foreach ($dashboards as $dashboard) {
$item = id(new PHUIObjectItemView())
->setViewer($viewer)
->setObjectName($dashboard->getObjectName())
->setHeader($dashboard->getName())
->setHref($dashboard->getURI())
->setObject($dashboard);
if ($dashboard->isArchived()) {
$item->setDisabled(true);
$bg_color = 'bg-grey';
} else {
$bg_color = 'bg-dark';
}
$icon = id(new PHUIIconView())
->setIcon($dashboard->getIcon())
->setBackground($bg_color);
$item->setImageIcon($icon);
$item->setEpoch($dashboard->getDateModified());
$author_phid = $dashboard->getAuthorPHID();
$author_name = $handles[$author_phid]->renderLink();
$item->addByline(pht('Author: %s', $author_name));
$phid = $dashboard->getPHID();
$project_phids = $edge_query->getDestinationPHIDs(array($phid));
$project_handles = $viewer->loadHandles($project_phids);
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setNoDataString(pht('No Tags'))
->setSlim(true)
->setHandles($project_handles));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No dashboards found.'));
return $result;
}
}
diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php
index ff3376bdf6..cc43c613c2 100644
--- a/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php
+++ b/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorDashboardDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Dashboards');
}
public function getPlaceholderText() {
return pht('Type a dashboard name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function loadResults() {
$query = id(new PhabricatorDashboardQuery());
$this->applyFerretConstraints(
$query,
id(new PhabricatorDashboard())->newFerretEngine(),
'title',
$this->getRawQuery());
$dashboards = $this->executeQuery($query);
$results = array();
foreach ($dashboards as $dashboard) {
$result = id(new PhabricatorTypeaheadResult())
->setName($dashboard->getName())
->setPHID($dashboard->getPHID())
->addAttribute(pht('Dashboard'));
if ($dashboard->isArchived()) {
$result->setClosed(pht('Archived'));
}
$results[] = $result;
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
index 9ad4901bbf..b6621480bc 100644
--- a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
+++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php
@@ -1,79 +1,79 @@
<?php
final class PhabricatorDashboardPanelDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Dashboard Panels');
}
public function getPlaceholderText() {
return pht('Type a panel name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
public function buildResults() {
$query = new PhabricatorDashboardPanelQuery();
$raw_query = $this->getRawQuery();
if (preg_match('/^[wW]\d+\z/', $raw_query)) {
$id = trim($raw_query, 'wW');
$id = (int)$id;
$query->withIDs(array($id));
} else {
$this->applyFerretConstraints(
$query,
id(new PhabricatorDashboardPanel())->newFerretEngine(),
'title',
$this->getRawQuery());
}
$panels = $this->executeQuery($query);
$results = array();
foreach ($panels as $panel) {
$impl = $panel->getImplementation();
if ($impl) {
$type_text = $impl->getPanelTypeName();
$icon = $impl->getIcon();
} else {
$type_text = nonempty($panel->getPanelType(), pht('Unknown Type'));
$icon = 'fa-question';
}
$phid = $panel->getPHID();
$monogram = $panel->getMonogram();
$properties = $panel->getProperties();
$result = id(new PhabricatorTypeaheadResult())
->setName($monogram.' '.$panel->getName())
->setPHID($phid)
->setIcon($icon)
->addAttribute($type_text);
if (!empty($properties['class'])) {
$result->addAttribute($properties['class']);
}
if ($panel->getIsArchived()) {
$result->setClosed(pht('Archived'));
}
$results[$phid] = $result;
}
return $results;
}
}
diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php
index 008bb542ab..2d2e17b6b1 100644
--- a/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php
+++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPortalDatasource.php
@@ -1,51 +1,51 @@
<?php
final class PhabricatorDashboardPortalDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Portals');
}
public function getPlaceholderText() {
return pht('Type a portal name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDashboardApplication';
+ return PhabricatorDashboardApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
public function buildResults() {
$query = new PhabricatorDashboardPortalQuery();
$this->applyFerretConstraints(
$query,
id(new PhabricatorDashboardPortal())->newFerretEngine(),
'title',
$this->getRawQuery());
$portals = $this->executeQuery($query);
$results = array();
foreach ($portals as $portal) {
$result = id(new PhabricatorTypeaheadResult())
->setName($portal->getObjectName().' '.$portal->getName())
->setPHID($portal->getPHID())
->setIcon('fa-compass');
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/differential/editor/DifferentialDiffEditor.php b/src/applications/differential/editor/DifferentialDiffEditor.php
index e78e08d808..eaaeee60fd 100644
--- a/src/applications/differential/editor/DifferentialDiffEditor.php
+++ b/src/applications/differential/editor/DifferentialDiffEditor.php
@@ -1,229 +1,229 @@
<?php
final class DifferentialDiffEditor
extends PhabricatorApplicationTransactionEditor {
private $diffDataDict;
private $lookupRepository = true;
public function setLookupRepository($bool) {
$this->lookupRepository = $bool;
return $this;
}
public function getEditorApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Differential Diffs');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = DifferentialDiffTransaction::TYPE_DIFF_CREATE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
$this->diffDataDict = $xaction->getNewValue();
return true;
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
$dict = $this->diffDataDict;
$this->updateDiffFromDict($object, $dict);
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// If we didn't get an explicit `repositoryPHID` (which means the client
// is old, or couldn't figure out which repository the working copy
// belongs to), apply heuristics to try to figure it out.
if ($this->lookupRepository && !$object->getRepositoryPHID()) {
$repository = id(new DifferentialRepositoryLookup())
->setDiff($object)
->setViewer($this->getActor())
->lookupRepository();
if ($repository) {
$object->setRepositoryPHID($repository->getPHID());
$object->setRepositoryUUID($repository->getUUID());
$object->save();
}
}
return $xactions;
}
/**
* We run Herald as part of transaction validation because Herald can
* block diff creation for Differential diffs. Its important to do this
* separately so no Herald logs are saved; these logs could expose
* information the Herald rules are intended to block.
*/
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
foreach ($xactions as $xaction) {
switch ($type) {
case DifferentialDiffTransaction::TYPE_DIFF_CREATE:
$diff = clone $object;
$diff = $this->updateDiffFromDict($diff, $xaction->getNewValue());
$adapter = $this->buildHeraldAdapter($diff, $xactions);
$adapter->setContentSource($this->getContentSource());
$adapter->setIsNewObject($this->getIsNewObject());
$engine = new HeraldEngine();
$rules = $engine->loadRulesForAdapter($adapter);
$rules = mpull($rules, null, 'getID');
$effects = $engine->applyRules($rules, $adapter);
$action_block = DifferentialBlockHeraldAction::ACTIONCONST;
$blocking_effect = null;
foreach ($effects as $effect) {
if ($effect->getAction() == $action_block) {
$blocking_effect = $effect;
break;
}
}
if ($blocking_effect) {
$rule = $blocking_effect->getRule();
$message = $effect->getTarget();
if (!strlen($message)) {
$message = pht('(None.)');
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Rejected by Herald'),
pht(
"Creation of this diff was rejected by Herald rule %s.\n".
" Rule: %s\n".
"Reason: %s",
$rule->getMonogram(),
$rule->getName(),
$message));
}
break;
}
}
return $errors;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return false;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return false;
}
protected function supportsSearch() {
return false;
}
/* -( Herald Integration )------------------------------------------------- */
/**
* See @{method:validateTransaction}. The only Herald action is to block
* the creation of Diffs. We thus have to be careful not to save any
* data and do this validation very early.
*/
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return false;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
$adapter = id(new HeraldDifferentialDiffAdapter())
->setDiff($object);
return $adapter;
}
private function updateDiffFromDict(DifferentialDiff $diff, $dict) {
$diff
->setSourcePath(idx($dict, 'sourcePath'))
->setSourceMachine(idx($dict, 'sourceMachine'))
->setBranch(idx($dict, 'branch'))
->setCreationMethod(idx($dict, 'creationMethod'))
->setAuthorPHID(idx($dict, 'authorPHID', $this->getActor()))
->setBookmark(idx($dict, 'bookmark'))
->setRepositoryPHID(idx($dict, 'repositoryPHID'))
->setRepositoryUUID(idx($dict, 'repositoryUUID'))
->setSourceControlSystem(idx($dict, 'sourceControlSystem'))
->setSourceControlPath(idx($dict, 'sourceControlPath'))
->setSourceControlBaseRevision(idx($dict, 'sourceControlBaseRevision'))
->setLintStatus(idx($dict, 'lintStatus'))
->setUnitStatus(idx($dict, 'unitStatus'));
return $diff;
}
}
diff --git a/src/applications/differential/editor/DifferentialRevisionEditEngine.php b/src/applications/differential/editor/DifferentialRevisionEditEngine.php
index bd1cee7c26..a0d0569069 100644
--- a/src/applications/differential/editor/DifferentialRevisionEditEngine.php
+++ b/src/applications/differential/editor/DifferentialRevisionEditEngine.php
@@ -1,386 +1,386 @@
<?php
final class DifferentialRevisionEditEngine
extends PhabricatorEditEngine {
private $diff;
const ENGINECONST = 'differential.revision';
const ACTIONGROUP_REVIEW = 'review';
const ACTIONGROUP_REVISION = 'revision';
public function getEngineName() {
return pht('Revisions');
}
public function getSummaryHeader() {
return pht('Configure Revision Forms');
}
public function getSummaryText() {
return pht(
'Configure creation and editing revision forms in Differential.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return DifferentialRevision::initializeNewRevision($viewer);
}
protected function newObjectQuery() {
return id(new DifferentialRevisionQuery())
->needActiveDiffs(true)
->needReviewers(true)
->needReviewerAuthority(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Revision');
}
protected function getObjectEditTitleText($object) {
$monogram = $object->getMonogram();
$title = $object->getTitle();
$diff = $this->getDiff();
if ($diff) {
return pht('Update Revision %s: %s', $monogram, $title);
} else {
return pht('Edit Revision %s: %s', $monogram, $title);
}
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
public function getCreateURI($form_key) {
return '/differential/diff/create/';
}
protected function getObjectCreateShortText() {
return pht('Create Revision');
}
protected function getObjectName() {
return pht('Revision');
}
protected function getCommentViewButtonText($object) {
if ($object->isDraft()) {
return pht('Submit Quietly');
}
return parent::getCommentViewButtonText($object);
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('revision/edit/');
}
public function setDiff(DifferentialDiff $diff) {
$this->diff = $diff;
return $this;
}
public function getDiff() {
return $this->diff;
}
protected function newCommentActionGroups() {
return array(
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_REVIEW)
->setLabel(pht('Review Actions')),
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_REVISION)
->setLabel(pht('Revision Actions')),
);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$plan_required = PhabricatorEnv::getEnvConfig(
'differential.require-test-plan-field');
$plan_enabled = $this->isCustomFieldEnabled(
$object,
'differential:test-plan');
$diff = $this->getDiff();
if ($diff) {
$diff_phid = $diff->getPHID();
} else {
$diff_phid = null;
}
$is_create = $this->getIsCreate();
$is_update = ($diff && !$is_create);
$fields = array();
$fields[] = id(new PhabricatorHandlesEditField())
->setKey(DifferentialRevisionUpdateTransaction::EDITKEY)
->setLabel(pht('Update Diff'))
->setDescription(pht('New diff to create or update the revision with.'))
->setConduitDescription(pht('Create or update a revision with a diff.'))
->setConduitTypeDescription(pht('PHID of the diff.'))
->setTransactionType(
DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE)
->setHandleParameterType(new AphrontPHIDListHTTPParameterType())
->setSingleValue($diff_phid)
->setIsFormField((bool)$diff)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsInvisible(true)
->setIsLockable(false);
if ($is_update) {
$fields[] = id(new PhabricatorInstructionsEditField())
->setKey('update.help')
->setValue(pht('Describe the updates you have made to the diff.'));
$fields[] = id(new PhabricatorCommentEditField())
->setKey('update.comment')
->setLabel(pht('Comment'))
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->setIsWebOnly(true)
->setDescription(pht('Comments providing context for the update.'));
$fields[] = id(new PhabricatorSubmitEditField())
->setKey('update.submit')
->setValue($this->getObjectEditButtonText($object));
$fields[] = id(new PhabricatorDividerEditField())
->setKey('update.note');
}
$fields[] = id(new PhabricatorTextEditField())
->setKey(DifferentialRevisionTitleTransaction::EDITKEY)
->setLabel(pht('Title'))
->setIsRequired(true)
->setTransactionType(
DifferentialRevisionTitleTransaction::TRANSACTIONTYPE)
->setDescription(pht('The title of the revision.'))
->setConduitDescription(pht('Retitle the revision.'))
->setConduitTypeDescription(pht('New revision title.'))
->setValue($object->getTitle());
$author_field = id(new PhabricatorDatasourceEditField())
->setKey(DifferentialRevisionAuthorTransaction::EDITKEY)
->setLabel(pht('Author'))
->setDatasource(new PhabricatorPeopleDatasource())
->setTransactionType(
DifferentialRevisionAuthorTransaction::TRANSACTIONTYPE)
->setDescription(pht('Foist this revision upon someone else.'))
->setConduitDescription(pht('Foist this revision upon another user.'))
->setConduitTypeDescription(pht('New author.'))
->setSingleValue($object->getAuthorPHID());
// Don't show the "Author" field when creating a revision using the web
// workflow, since it adds more noise than signal to this workflow.
if ($is_create) {
$author_field->setIsHidden(true);
}
// Only show the "Foist Upon" comment action to the current revision
// author. Other users can use "Edit Revision", it's just very unlikley
// that they're interested in this action.
if ($viewer->getPHID() === $object->getAuthorPHID()) {
$author_field->setCommentActionLabel(pht('Foist Upon'));
}
$fields[] = $author_field;
$fields[] = id(new PhabricatorRemarkupEditField())
->setKey(DifferentialRevisionSummaryTransaction::EDITKEY)
->setLabel(pht('Summary'))
->setTransactionType(
DifferentialRevisionSummaryTransaction::TRANSACTIONTYPE)
->setDescription(pht('The summary of the revision.'))
->setConduitDescription(pht('Change the revision summary.'))
->setConduitTypeDescription(pht('New revision summary.'))
->setValue($object->getSummary());
if ($plan_enabled) {
$fields[] = id(new PhabricatorRemarkupEditField())
->setKey(DifferentialRevisionTestPlanTransaction::EDITKEY)
->setLabel(pht('Test Plan'))
->setIsRequired($plan_required)
->setTransactionType(
DifferentialRevisionTestPlanTransaction::TRANSACTIONTYPE)
->setDescription(
pht('Actions performed to verify the behavior of the change.'))
->setConduitDescription(pht('Update the revision test plan.'))
->setConduitTypeDescription(pht('New test plan.'))
->setValue($object->getTestPlan());
}
$fields[] = id(new PhabricatorDatasourceEditField())
->setKey(DifferentialRevisionReviewersTransaction::EDITKEY)
->setLabel(pht('Reviewers'))
->setDatasource(new DifferentialReviewerDatasource())
->setUseEdgeTransactions(true)
->setTransactionType(
DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE)
->setCommentActionLabel(pht('Change Reviewers'))
->setDescription(pht('Reviewers for this revision.'))
->setConduitDescription(pht('Change the reviewers for this revision.'))
->setConduitTypeDescription(pht('New reviewers.'))
->setValue($object->getReviewerPHIDsForEdit());
// Prefill Repository for example when coming from "Attach To".
$repository_phid = $object->getRepositoryPHID();
if ($is_create && !$repository_phid && $diff) {
$repository_phid = $diff->getRepositoryPHID();
}
$fields[] = id(new PhabricatorDatasourceEditField())
->setKey('repositoryPHID')
->setLabel(pht('Repository'))
->setDatasource(new DiffusionRepositoryDatasource())
->setTransactionType(
DifferentialRevisionRepositoryTransaction::TRANSACTIONTYPE)
->setDescription(pht('The repository the revision belongs to.'))
->setConduitDescription(pht('Change the repository for this revision.'))
->setConduitTypeDescription(pht('New repository.'))
->setSingleValue($repository_phid);
// This is a little flimsy, but allows "Maniphest Tasks: ..." to continue
// working properly in commit messages until we fully sort out T5873.
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('tasks')
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
DifferentialRevisionHasTaskEdgeType::EDGECONST)
->setDescription(pht('Tasks associated with this revision.'))
->setConduitDescription(pht('Change associated tasks.'))
->setConduitTypeDescription(pht('List of tasks.'))
->setValue(array());
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('parents')
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST)
->setDescription(pht('Parent revisions of this revision.'))
->setConduitDescription(pht('Change associated parent revisions.'))
->setConduitTypeDescription(pht('List of revisions.'))
->setValue(array());
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('children')
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
DifferentialRevisionDependedOnByRevisionEdgeType::EDGECONST)
->setDescription(pht('Child revisions of this revision.'))
->setConduitDescription(pht('Change associated child revisions.'))
->setConduitTypeDescription(pht('List of revisions.'))
->setValue(array());
$actions = DifferentialRevisionActionTransaction::loadAllActions();
$actions = msortv($actions, 'getRevisionActionOrderVector');
foreach ($actions as $key => $action) {
$fields[] = $action->newEditField($object, $viewer);
}
$fields[] = id(new PhabricatorBoolEditField())
->setKey('draft')
->setLabel(pht('Hold as Draft'))
->setIsFormField(false)
->setOptions(
pht('Autosubmit Once Builds Finish'),
pht('Hold as Draft'))
->setTransactionType(
DifferentialRevisionHoldDraftTransaction::TRANSACTIONTYPE)
->setDescription(pht('Hold revision as draft.'))
->setConduitDescription(
pht(
'Change autosubmission from draft state after builds finish.'))
->setConduitTypeDescription(pht('New "Hold as Draft" setting.'))
->setValue($object->getHoldAsDraft());
return $fields;
}
private function isCustomFieldEnabled(DifferentialRevision $revision, $key) {
$field_list = PhabricatorCustomField::getObjectFields(
$revision,
PhabricatorCustomField::ROLE_VIEW);
$fields = $field_list->getFields();
return isset($fields[$key]);
}
protected function newAutomaticCommentTransactions($object) {
$viewer = $this->getViewer();
$editor = $object->getApplicationTransactionEditor()
->setActor($viewer);
$xactions = $editor->newAutomaticInlineTransactions(
$object,
DifferentialTransaction::TYPE_INLINE,
new DifferentialDiffInlineCommentQuery());
return $xactions;
}
protected function newCommentPreviewContent($object, array $xactions) {
$viewer = $this->getViewer();
$type_inline = DifferentialTransaction::TYPE_INLINE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() === $type_inline) {
$inlines[] = $xaction->getComment();
}
}
$content = array();
if ($inlines) {
// Reload inlines to get inline context.
$inlines = id(new DifferentialDiffInlineCommentQuery())
->setViewer($viewer)
->withIDs(mpull($inlines, 'getID'))
->needInlineContext(true)
->execute();
$inline_preview = id(new PHUIDiffInlineCommentPreviewListView())
->setViewer($viewer)
->setInlineComments($inlines);
$content[] = phutil_tag(
'div',
array(
'id' => 'inline-comment-preview',
),
$inline_preview);
}
return $content;
}
}
diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php
index b935b09b2d..9ceb493b5f 100644
--- a/src/applications/differential/editor/DifferentialTransactionEditor.php
+++ b/src/applications/differential/editor/DifferentialTransactionEditor.php
@@ -1,1690 +1,1690 @@
<?php
final class DifferentialTransactionEditor
extends PhabricatorApplicationTransactionEditor {
private $changedPriorToCommitURI;
private $isCloseByCommit;
private $repositoryPHIDOverride = false;
private $didExpandInlineState = false;
private $firstBroadcast = false;
private $wasBroadcasting;
private $isDraftDemotion;
private $ownersDiff;
private $ownersChangesets;
public function getEditorApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Differential Revisions');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this revision.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function isFirstBroadcast() {
return $this->firstBroadcast;
}
public function getDiffUpdateTransaction(array $xactions) {
$type_update = DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $type_update) {
return $xaction;
}
}
return null;
}
public function setIsCloseByCommit($is_close_by_commit) {
$this->isCloseByCommit = $is_close_by_commit;
return $this;
}
public function getIsCloseByCommit() {
return $this->isCloseByCommit;
}
public function setChangedPriorToCommitURI($uri) {
$this->changedPriorToCommitURI = $uri;
return $this;
}
public function getChangedPriorToCommitURI() {
return $this->changedPriorToCommitURI;
}
public function setRepositoryPHIDOverride($phid_or_null) {
$this->repositoryPHIDOverride = $phid_or_null;
return $this;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_INLINESTATE;
$types[] = DifferentialTransaction::TYPE_INLINE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE:
return null;
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE:
$comment = $xaction->getComment();
$comment->setAttribute('editing', false);
PhabricatorVersionedDraft::purgeDrafts(
$comment->getPHID(),
$this->getActingAsPHID());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_INLINESTATE:
// If we have an "Inline State" transaction already, the caller
// built it for us so we don't need to expand it again.
$this->didExpandInlineState = true;
break;
case DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE:
if ($xaction->getMetadataValue('draft.demote')) {
$this->isDraftDemotion = true;
}
break;
}
}
$this->wasBroadcasting = $object->getShouldBroadcast();
return parent::expandTransactions($object, $xactions);
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$results = parent::expandTransaction($object, $xaction);
$actor = $this->getActor();
$actor_phid = $this->getActingAsPHID();
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$edge_ref_task = DifferentialRevisionHasTaskEdgeType::EDGECONST;
$want_downgrade = array();
$must_downgrade = array();
if ($this->getIsCloseByCommit()) {
// Never downgrade reviewers when we're closing a revision after a
// commit.
} else {
switch ($xaction->getTransactionType()) {
case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE:
$want_downgrade[] = DifferentialReviewerStatus::STATUS_ACCEPTED;
$want_downgrade[] = DifferentialReviewerStatus::STATUS_REJECTED;
break;
case DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE:
if (!$object->isChangePlanned()) {
// If the old state isn't "Changes Planned", downgrade the accepts
// even if they're sticky.
// We don't downgrade for "Changes Planned" to allow an author to
// undo a "Plan Changes" by immediately following it up with a
// "Request Review".
$want_downgrade[] = DifferentialReviewerStatus::STATUS_ACCEPTED;
$must_downgrade[] = DifferentialReviewerStatus::STATUS_ACCEPTED;
}
$want_downgrade[] = DifferentialReviewerStatus::STATUS_REJECTED;
break;
}
}
if ($want_downgrade) {
$void_type = DifferentialRevisionVoidTransaction::TRANSACTIONTYPE;
$results[] = id(new DifferentialTransaction())
->setTransactionType($void_type)
->setIgnoreOnNoEffect(true)
->setMetadataValue('void.force', $must_downgrade)
->setNewValue($want_downgrade);
}
$new_author_phid = null;
switch ($xaction->getTransactionType()) {
case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE:
if ($this->getIsCloseByCommit()) {
// Don't bother with any of this if this update is a side effect of
// commit detection.
break;
}
// When a revision is updated and the diff comes from a branch named
// "T123" or similar, automatically associate the commit with the
// task that the branch names.
$maniphest = 'PhabricatorManiphestApplication';
if (PhabricatorApplication::isClassInstalled($maniphest)) {
$diff = $this->requireDiff($xaction->getNewValue());
$branch = $diff->getBranch();
// No "$", to allow for branches like T123_demo.
$match = null;
if ($branch !== null && preg_match('/^T(\d+)/i', $branch, $match)) {
$task_id = $match[1];
$tasks = id(new ManiphestTaskQuery())
->setViewer($this->getActor())
->withIDs(array($task_id))
->execute();
if ($tasks) {
$task = head($tasks);
$task_phid = $task->getPHID();
$results[] = id(new DifferentialTransaction())
->setTransactionType($type_edge)
->setMetadataValue('edge:type', $edge_ref_task)
->setIgnoreOnNoEffect(true)
->setNewValue(array('+' => array($task_phid => $task_phid)));
}
}
}
break;
case DifferentialRevisionCommandeerTransaction::TRANSACTIONTYPE:
$new_author_phid = $actor_phid;
break;
case DifferentialRevisionAuthorTransaction::TRANSACTIONTYPE:
$new_author_phid = $xaction->getNewValue();
break;
}
if ($new_author_phid) {
$swap_xaction = $this->newSwapReviewersTransaction(
$object,
$new_author_phid);
if ($swap_xaction) {
$results[] = $swap_xaction;
}
}
if (!$this->didExpandInlineState) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE:
case DifferentialTransaction::TYPE_INLINE:
$this->didExpandInlineState = true;
$query_template = id(new DifferentialDiffInlineCommentQuery())
->withRevisionPHIDs(array($object->getPHID()));
$state_xaction = $this->newInlineStateTransaction(
$object,
$query_template);
if ($state_xaction) {
$results[] = $state_xaction;
}
break;
}
}
return $results;
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialTransaction::TYPE_INLINE:
$reply = $xaction->getComment()->getReplyToComment();
if ($reply && !$reply->getHasReplies()) {
$reply->setHasReplies(1)->save();
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function applyBuiltinExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_INLINESTATE:
$table = new DifferentialTransactionComment();
$conn_w = $table->establishConnection('w');
foreach ($xaction->getNewValue() as $phid => $state) {
queryfx(
$conn_w,
'UPDATE %T SET fixedState = %s WHERE phid = %s',
$table->getTableName(),
$state,
$phid);
}
break;
}
return parent::applyBuiltinExternalTransaction($object, $xaction);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// Load the most up-to-date version of the revision and its reviewers,
// so we don't need to try to deduce the state of reviewers by examining
// all the changes made by the transactions. Then, update the reviewers
// on the object to make sure we're acting on the current reviewer set
// (and, for example, sending mail to the right people).
$new_revision = id(new DifferentialRevisionQuery())
->setViewer($this->getActor())
->needReviewers(true)
->needActiveDiffs(true)
->withIDs(array($object->getID()))
->executeOne();
if (!$new_revision) {
throw new Exception(
pht('Failed to load revision from transaction finalization.'));
}
$active_diff = $new_revision->getActiveDiff();
$new_diff_phid = $active_diff->getPHID();
$object->attachReviewers($new_revision->getReviewers());
$object->attachActiveDiff($active_diff);
$object->attachRepository($new_revision->getRepository());
$has_new_diff = false;
$should_index_paths = false;
$should_index_hashes = false;
$need_changesets = false;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE:
$need_changesets = true;
$new_diff_phid = $xaction->getNewValue();
$has_new_diff = true;
$should_index_paths = true;
$should_index_hashes = true;
break;
case DifferentialRevisionRepositoryTransaction::TRANSACTIONTYPE:
// The "AffectedPath" table denormalizes the repository, so we
// want to update the index if the repository changes.
$need_changesets = true;
$should_index_paths = true;
break;
}
}
if ($need_changesets) {
$new_diff = $this->requireDiff($new_diff_phid, true);
if ($should_index_paths) {
id(new DifferentialAffectedPathEngine())
->setRevision($object)
->setDiff($new_diff)
->updateAffectedPaths();
}
if ($should_index_hashes) {
$this->updateRevisionHashTable($object, $new_diff);
}
if ($has_new_diff) {
$this->ownersDiff = $new_diff;
$this->ownersChangesets = $new_diff->getChangesets();
}
}
$xactions = $this->updateReviewStatus($object, $xactions);
$this->markReviewerComments($object, $xactions);
return $xactions;
}
private function updateReviewStatus(
DifferentialRevision $revision,
array $xactions) {
$was_accepted = $revision->isAccepted();
$was_revision = $revision->isNeedsRevision();
$was_review = $revision->isNeedsReview();
if (!$was_accepted && !$was_revision && !$was_review) {
// Revisions can't transition out of other statuses (like closed or
// abandoned) as a side effect of reviewer status changes.
return $xactions;
}
// Try to move a revision to "accepted". We look for:
//
// - at least one accepting reviewer who is a user; and
// - no rejects; and
// - no rejects of older diffs; and
// - no blocking reviewers.
$has_accepting_user = false;
$has_rejecting_reviewer = false;
$has_rejecting_older_reviewer = false;
$has_blocking_reviewer = false;
$active_diff = $revision->getActiveDiff();
foreach ($revision->getReviewers() as $reviewer) {
$reviewer_status = $reviewer->getReviewerStatus();
switch ($reviewer_status) {
case DifferentialReviewerStatus::STATUS_REJECTED:
$active_phid = $active_diff->getPHID();
if ($reviewer->isRejected($active_phid)) {
$has_rejecting_reviewer = true;
} else {
$has_rejecting_older_reviewer = true;
}
break;
case DifferentialReviewerStatus::STATUS_REJECTED_OLDER:
$has_rejecting_older_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_BLOCKING:
$has_blocking_reviewer = true;
break;
case DifferentialReviewerStatus::STATUS_ACCEPTED:
if ($reviewer->isUser()) {
$active_phid = $active_diff->getPHID();
if ($reviewer->isAccepted($active_phid)) {
$has_accepting_user = true;
}
}
break;
}
}
$new_status = null;
if ($has_accepting_user &&
!$has_rejecting_reviewer &&
!$has_rejecting_older_reviewer &&
!$has_blocking_reviewer) {
$new_status = DifferentialRevisionStatus::ACCEPTED;
} else if ($has_rejecting_reviewer) {
// This isn't accepted, and there's at least one rejecting reviewer,
// so the revision needs changes. This usually happens after a
// "reject".
$new_status = DifferentialRevisionStatus::NEEDS_REVISION;
} else if ($was_accepted) {
// This revision was accepted, but it no longer satisfies the
// conditions for acceptance. This usually happens after an accepting
// reviewer resigns or is removed.
$new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
} else if ($was_revision) {
// This revision was "Needs Revision", but no longer has any rejecting
// reviewers. This usually happens after the last rejecting reviewer
// resigns or is removed. Put the revision back in "Needs Review".
$new_status = DifferentialRevisionStatus::NEEDS_REVIEW;
}
if ($new_status === null) {
return $xactions;
}
$old_status = $revision->getModernRevisionStatus();
if ($new_status == $old_status) {
return $xactions;
}
$xaction = id(new DifferentialTransaction())
->setTransactionType(
DifferentialRevisionStatusTransaction::TRANSACTIONTYPE)
->setOldValue($old_status)
->setNewValue($new_status);
$xaction = $this->populateTransaction($revision, $xaction)
->save();
$xactions[] = $xaction;
// Save the status adjustment we made earlier.
$revision
->setModernRevisionStatus($new_status)
->save();
return $xactions;
}
protected function sortTransactions(array $xactions) {
$xactions = parent::sortTransactions($xactions);
$head = array();
$tail = array();
foreach ($xactions as $xaction) {
$type = $xaction->getTransactionType();
if ($type == DifferentialTransaction::TYPE_INLINE) {
$tail[] = $xaction;
} else {
$head[] = $xaction;
}
}
return array_values(array_merge($head, $tail));
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
if (!$object->getShouldBroadcast()) {
return false;
}
return true;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
if ($object->getShouldBroadcast()) {
$this->requireReviewers($object);
$phids = array();
$phids[] = $object->getAuthorPHID();
foreach ($object->getReviewers() as $reviewer) {
if ($reviewer->isResigned()) {
continue;
}
$phids[] = $reviewer->getReviewerPHID();
}
return $phids;
}
// If we're demoting a draft after a build failure, just notify the author.
if ($this->isDraftDemotion) {
$author_phid = $object->getAuthorPHID();
return array(
$author_phid,
);
}
return array();
}
protected function getMailCC(PhabricatorLiskDAO $object) {
if (!$object->getShouldBroadcast()) {
return array();
}
return parent::getMailCC($object);
}
protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) {
$this->requireReviewers($object);
$phids = array();
foreach ($object->getReviewers() as $reviewer) {
if ($reviewer->isResigned()) {
$phids[] = $reviewer->getReviewerPHID();
}
}
return $phids;
}
protected function getMailAction(
PhabricatorLiskDAO $object,
array $xactions) {
$show_lines = false;
if ($this->isFirstBroadcast()) {
$action = pht('Request');
$show_lines = true;
} else {
$action = parent::getMailAction($object, $xactions);
$strongest = $this->getStrongestAction($object, $xactions);
$type_update = DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE;
if ($strongest->getTransactionType() == $type_update) {
$show_lines = true;
}
}
if ($show_lines) {
$count = new PhutilNumber($object->getLineCount());
$action = pht('%s] [%s', $action, $object->getRevisionScaleGlyphs());
}
return $action;
}
protected function getMailSubjectPrefix() {
return pht('[Differential]');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
// This is nonstandard, but retains threading with older messages.
$phid = $object->getPHID();
return "differential-rev-{$phid}-req";
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new DifferentialReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$title = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject(pht('%s: %s', $monogram, $title))
->setMustEncryptSubject(pht('%s: Revision Updated', $monogram))
->setMustEncryptURI($object->getURI());
}
protected function getTransactionsForMail(
PhabricatorLiskDAO $object,
array $xactions) {
// If this is the first time we're sending mail about this revision, we
// generate mail for all prior transactions, not just whatever is being
// applied now. This gets the "added reviewers" lines and other relevant
// information into the mail.
if ($this->isFirstBroadcast()) {
return $this->loadUnbroadcastTransactions($object);
}
return $xactions;
}
protected function getObjectLinkButtonLabelForMail(
PhabricatorLiskDAO $object) {
return pht('View Revision');
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$viewer = $this->requireActor();
$body = id(new PhabricatorMetaMTAMailBody())
->setViewer($viewer);
$revision_uri = $this->getObjectLinkButtonURIForMail($object);
$new_uri = $revision_uri.'/new/';
$this->addHeadersAndCommentsToMailBody(
$body,
$xactions,
$this->getObjectLinkButtonLabelForMail($object),
$revision_uri);
$type_inline = DifferentialTransaction::TYPE_INLINE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $type_inline) {
$inlines[] = $xaction;
}
}
if ($inlines) {
$this->appendInlineCommentsForMail($object, $inlines, $body);
}
$update_xaction = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE:
$update_xaction = $xaction;
break;
}
}
if ($update_xaction) {
$diff = $this->requireDiff($update_xaction->getNewValue(), true);
} else {
$diff = null;
}
$changed_uri = $this->getChangedPriorToCommitURI();
if ($changed_uri) {
$body->addLinkSection(
pht('CHANGED PRIOR TO COMMIT'),
$changed_uri);
}
$this->addCustomFieldsToMailBody($body, $object, $xactions);
if (!$this->isFirstBroadcast()) {
$body->addLinkSection(pht('CHANGES SINCE LAST ACTION'), $new_uri);
}
$body->addLinkSection(
pht('REVISION DETAIL'),
$revision_uri);
if ($update_xaction) {
$body->addTextSection(
pht('AFFECTED FILES'),
$this->renderAffectedFilesForMail($diff));
$config_key_inline = 'metamta.differential.inline-patches';
$config_inline = PhabricatorEnv::getEnvConfig($config_key_inline);
$config_key_attach = 'metamta.differential.attach-patches';
$config_attach = PhabricatorEnv::getEnvConfig($config_key_attach);
if ($config_inline || $config_attach) {
$body_limit = PhabricatorEnv::getEnvConfig('metamta.email-body-limit');
try {
$patch = $this->buildPatchForMail($diff, $body_limit);
} catch (ArcanistDiffByteSizeException $ex) {
$patch = null;
}
if (($patch !== null) && $config_inline) {
$lines = substr_count($patch, "\n");
$bytes = strlen($patch);
// Limit the patch size to the smaller of 256 bytes per line or
// the mail body limit. This prevents degenerate behavior for patches
// with one line that is 10MB long. See T11748.
$byte_limits = array();
$byte_limits[] = (256 * $config_inline);
$byte_limits[] = $body_limit;
$byte_limit = min($byte_limits);
$lines_ok = ($lines <= $config_inline);
$bytes_ok = ($bytes <= $byte_limit);
if ($lines_ok && $bytes_ok) {
$this->appendChangeDetailsForMail($object, $diff, $patch, $body);
} else {
// TODO: Provide a helpful message about the patch being too
// large or lengthy here.
}
}
if (($patch !== null) && $config_attach) {
// See T12033, T11767, and PHI55. This is a crude fix to stop the
// major concrete problems that lackluster email size limits cause.
if (strlen($patch) < $body_limit) {
$name = pht('D%s.%s.patch', $object->getID(), $diff->getID());
$mime_type = 'text/x-patch; charset=utf-8';
$body->addAttachment(
new PhabricatorMailAttachment($patch, $name, $mime_type));
}
}
}
}
return $body;
}
public function getMailTagsMap() {
return array(
DifferentialTransaction::MAILTAG_REVIEW_REQUEST =>
pht('A revision is created.'),
DifferentialTransaction::MAILTAG_UPDATED =>
pht('A revision is updated.'),
DifferentialTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a revision.'),
DifferentialTransaction::MAILTAG_CLOSED =>
pht('A revision is closed.'),
DifferentialTransaction::MAILTAG_REVIEWERS =>
pht("A revision's reviewers change."),
DifferentialTransaction::MAILTAG_CC =>
pht("A revision's CCs change."),
DifferentialTransaction::MAILTAG_OTHER =>
pht('Other revision activity not listed above occurs.'),
);
}
protected function supportsSearch() {
return true;
}
protected function expandCustomRemarkupBlockTransactions(
PhabricatorLiskDAO $object,
array $xactions,
array $changes,
PhutilMarkupEngine $engine) {
// For "Fixes ..." and "Depends on ...", we're only going to look at
// content blocks which are part of the revision itself (like "Summary"
// and "Test Plan"), not comments.
$content_parts = array();
foreach ($changes as $change) {
if ($change->getTransaction()->isCommentTransaction()) {
continue;
}
$content_parts[] = $change->getNewValue();
}
if (!$content_parts) {
return array();
}
$content_block = implode("\n\n", $content_parts);
$task_map = array();
$task_refs = id(new ManiphestCustomFieldStatusParser())
->parseCorpus($content_block);
foreach ($task_refs as $match) {
foreach ($match['monograms'] as $monogram) {
$task_id = (int)trim($monogram, 'tT');
$task_map[$task_id] = true;
}
}
$rev_map = array();
$rev_refs = id(new DifferentialCustomFieldDependsOnParser())
->parseCorpus($content_block);
foreach ($rev_refs as $match) {
foreach ($match['monograms'] as $monogram) {
$rev_id = (int)trim($monogram, 'dD');
$rev_map[$rev_id] = true;
}
}
$edges = array();
$task_phids = array();
$rev_phids = array();
if ($task_map) {
$tasks = id(new ManiphestTaskQuery())
->setViewer($this->getActor())
->withIDs(array_keys($task_map))
->execute();
if ($tasks) {
$task_phids = mpull($tasks, 'getPHID', 'getPHID');
$edge_related = DifferentialRevisionHasTaskEdgeType::EDGECONST;
$edges[$edge_related] = $task_phids;
}
}
if ($rev_map) {
$revs = id(new DifferentialRevisionQuery())
->setViewer($this->getActor())
->withIDs(array_keys($rev_map))
->execute();
$rev_phids = mpull($revs, 'getPHID', 'getPHID');
// NOTE: Skip any write attempts if a user cleverly implies a revision
// depends upon itself.
unset($rev_phids[$object->getPHID()]);
if ($revs) {
$depends = DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST;
$edges[$depends] = $rev_phids;
}
}
$revert_refs = id(new DifferentialCustomFieldRevertsParser())
->parseCorpus($content_block);
$revert_monograms = array();
foreach ($revert_refs as $match) {
foreach ($match['monograms'] as $monogram) {
$revert_monograms[] = $monogram;
}
}
if ($revert_monograms) {
$revert_objects = DiffusionCommitRevisionQuery::loadRevertedObjects(
$this->getActor(),
$object,
$revert_monograms,
null);
$revert_phids = mpull($revert_objects, 'getPHID', 'getPHID');
$revert_type = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
$edges[$revert_type] = $revert_phids;
} else {
$revert_phids = array();
}
$this->addUnmentionablePHIDs($task_phids);
$this->addUnmentionablePHIDs($rev_phids);
$this->addUnmentionablePHIDs($revert_phids);
$result = array();
foreach ($edges as $type => $specs) {
$result[] = id(new DifferentialTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $type)
->setNewValue(array('+' => $specs));
}
return $result;
}
private function appendInlineCommentsForMail(
PhabricatorLiskDAO $object,
array $inlines,
PhabricatorMetaMTAMailBody $body) {
$limit = 100;
$limit_note = null;
if (count($inlines) > $limit) {
$limit_note = pht(
'(Showing first %s of %s inline comments.)',
new PhutilNumber($limit),
phutil_count($inlines));
$inlines = array_slice($inlines, 0, $limit, true);
}
$section = id(new DifferentialInlineCommentMailView())
->setViewer($this->getActor())
->setInlines($inlines)
->buildMailSection();
$header = pht('INLINE COMMENTS');
$section_text = "\n".$section->getPlaintext();
if ($limit_note) {
$section_text = $limit_note."\n".$section_text;
}
$style = array(
'margin: 6px 0 12px 0;',
);
$section_html = phutil_tag(
'div',
array(
'style' => implode(' ', $style),
),
$section->getHTML());
if ($limit_note) {
$section_html = array(
phutil_tag(
'em',
array(),
$limit_note),
$section_html,
);
}
$body->addPlaintextSection($header, $section_text, false);
$body->addHTMLSection($header, $section_html);
}
private function appendChangeDetailsForMail(
PhabricatorLiskDAO $object,
DifferentialDiff $diff,
$patch,
PhabricatorMetaMTAMailBody $body) {
$section = id(new DifferentialChangeDetailMailView())
->setViewer($this->getActor())
->setDiff($diff)
->setPatch($patch)
->buildMailSection();
$header = pht('CHANGE DETAILS');
$section_text = "\n".$section->getPlaintext();
$style = array(
'margin: 6px 0 12px 0;',
);
$section_html = phutil_tag(
'div',
array(
'style' => implode(' ', $style),
),
$section->getHTML());
$body->addPlaintextSection($header, $section_text, false);
$body->addHTMLSection($header, $section_html);
}
private function loadDiff($phid, $need_changesets = false) {
$query = id(new DifferentialDiffQuery())
->withPHIDs(array($phid))
->setViewer($this->getActor());
if ($need_changesets) {
$query->needChangesets(true);
}
return $query->executeOne();
}
public function requireDiff($phid, $need_changesets = false) {
$diff = $this->loadDiff($phid, $need_changesets);
if (!$diff) {
throw new Exception(pht('Diff "%s" does not exist!', $phid));
}
return $diff;
}
/* -( Herald Integration )------------------------------------------------- */
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function didApplyHeraldRules(
PhabricatorLiskDAO $object,
HeraldAdapter $adapter,
HeraldTranscript $transcript) {
$repository = $object->getRepository();
if (!$repository) {
return array();
}
$diff = $this->ownersDiff;
$changesets = $this->ownersChangesets;
$this->ownersDiff = null;
$this->ownersChangesets = null;
if (!$changesets) {
return array();
}
$packages = PhabricatorOwnersPackage::loadAffectedPackagesForChangesets(
$repository,
$diff,
$changesets);
if (!$packages) {
return array();
}
// Identify the packages with "Non-Owner Author" review rules and remove
// them if the author has authority over the package.
$autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap();
$need_authority = array();
foreach ($packages as $package) {
$autoreview_setting = $package->getAutoReview();
$spec = idx($autoreview_map, $autoreview_setting);
if (!$spec) {
continue;
}
if (idx($spec, 'authority')) {
$need_authority[$package->getPHID()] = $package->getPHID();
}
}
if ($need_authority) {
$authority = id(new PhabricatorOwnersPackageQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($need_authority)
->withAuthorityPHIDs(array($object->getAuthorPHID()))
->execute();
$authority = mpull($authority, null, 'getPHID');
foreach ($packages as $key => $package) {
$package_phid = $package->getPHID();
if (isset($authority[$package_phid])) {
unset($packages[$key]);
continue;
}
}
if (!$packages) {
return array();
}
}
$auto_subscribe = array();
$auto_review = array();
$auto_block = array();
foreach ($packages as $package) {
switch ($package->getAutoReview()) {
case PhabricatorOwnersPackage::AUTOREVIEW_REVIEW:
case PhabricatorOwnersPackage::AUTOREVIEW_REVIEW_ALWAYS:
$auto_review[] = $package;
break;
case PhabricatorOwnersPackage::AUTOREVIEW_BLOCK:
case PhabricatorOwnersPackage::AUTOREVIEW_BLOCK_ALWAYS:
$auto_block[] = $package;
break;
case PhabricatorOwnersPackage::AUTOREVIEW_SUBSCRIBE:
case PhabricatorOwnersPackage::AUTOREVIEW_SUBSCRIBE_ALWAYS:
$auto_subscribe[] = $package;
break;
case PhabricatorOwnersPackage::AUTOREVIEW_NONE:
default:
break;
}
}
$owners_phid = id(new PhabricatorOwnersApplication())
->getPHID();
$xactions = array();
if ($auto_subscribe) {
$xactions[] = $object->getApplicationTransactionTemplate()
->setAuthorPHID($owners_phid)
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(
array(
'+' => mpull($auto_subscribe, 'getPHID'),
));
}
$specs = array(
array($auto_review, false),
array($auto_block, true),
);
foreach ($specs as $spec) {
list($reviewers, $blocking) = $spec;
if (!$reviewers) {
continue;
}
$phids = mpull($reviewers, 'getPHID');
$xaction = $this->newAutoReviewTransaction($object, $phids, $blocking);
if ($xaction) {
$xactions[] = $xaction;
}
}
return $xactions;
}
private function newAutoReviewTransaction(
PhabricatorLiskDAO $object,
array $phids,
$is_blocking) {
// TODO: This is substantially similar to DifferentialReviewersHeraldAction
// and both are needlessly complex. This logic should live in the normal
// transaction application pipeline. See T10967.
$reviewers = $object->getReviewers();
$reviewers = mpull($reviewers, null, 'getReviewerPHID');
if ($is_blocking) {
$new_status = DifferentialReviewerStatus::STATUS_BLOCKING;
} else {
$new_status = DifferentialReviewerStatus::STATUS_ADDED;
}
$new_strength = DifferentialReviewerStatus::getStatusStrength(
$new_status);
$current = array();
foreach ($phids as $phid) {
if (!isset($reviewers[$phid])) {
continue;
}
// If we're applying a stronger status (usually, upgrading a reviewer
// into a blocking reviewer), skip this check so we apply the change.
$old_strength = DifferentialReviewerStatus::getStatusStrength(
$reviewers[$phid]->getReviewerStatus());
if ($old_strength <= $new_strength) {
continue;
}
$current[] = $phid;
}
$phids = array_diff($phids, $current);
if (!$phids) {
return null;
}
$phids = array_fuse($phids);
$value = array();
foreach ($phids as $phid) {
if ($is_blocking) {
$value[] = 'blocking('.$phid.')';
} else {
$value[] = $phid;
}
}
$owners_phid = id(new PhabricatorOwnersApplication())
->getPHID();
$reviewers_type = DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE;
return $object->getApplicationTransactionTemplate()
->setAuthorPHID($owners_phid)
->setTransactionType($reviewers_type)
->setNewValue(
array(
'+' => $value,
));
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
$revision = id(new DifferentialRevisionQuery())
->setViewer($this->getActor())
->withPHIDs(array($object->getPHID()))
->needActiveDiffs(true)
->needReviewers(true)
->executeOne();
if (!$revision) {
throw new Exception(
pht('Failed to load revision for Herald adapter construction!'));
}
$adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter(
$revision,
$revision->getActiveDiff());
// If the object is still a draft, prevent "Send me an email" and other
// similar rules from acting yet.
if (!$object->getShouldBroadcast()) {
$adapter->setForbiddenAction(
HeraldMailableState::STATECONST,
DifferentialHeraldStateReasons::REASON_DRAFT);
}
// If this edit didn't actually change the diff (for example, a user
// edited the title or changed subscribers), prevent "Run build plan"
// and other similar rules from acting yet, since the build results will
// not (or, at least, should not) change unless the actual source changes.
// We also don't run Differential builds if the update was caused by
// discovering a commit, as the expectation is that Diffusion builds take
// over once things land.
$has_update = false;
$has_commit = false;
$type_update = DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() != $type_update) {
continue;
}
if ($xaction->getMetadataValue('isCommitUpdate')) {
$has_commit = true;
} else {
$has_update = true;
}
break;
}
if ($has_commit) {
$adapter->setForbiddenAction(
HeraldBuildableState::STATECONST,
DifferentialHeraldStateReasons::REASON_LANDED);
} else if (!$has_update) {
$adapter->setForbiddenAction(
HeraldBuildableState::STATECONST,
DifferentialHeraldStateReasons::REASON_UNCHANGED);
}
return $adapter;
}
/**
* Update the table connecting revisions to DVCS local hashes, so we can
* identify revisions by commit/tree hashes.
*/
private function updateRevisionHashTable(
DifferentialRevision $revision,
DifferentialDiff $diff) {
$vcs = $diff->getSourceControlSystem();
if ($vcs == DifferentialRevisionControlSystem::SVN) {
// Subversion has no local commit or tree hash information, so we don't
// have to do anything.
return;
}
$property = id(new DifferentialDiffProperty())->loadOneWhere(
'diffID = %d AND name = %s',
$diff->getID(),
'local:commits');
if (!$property) {
return;
}
$hashes = array();
$data = $property->getData();
switch ($vcs) {
case DifferentialRevisionControlSystem::GIT:
foreach ($data as $commit) {
$hashes[] = array(
ArcanistDifferentialRevisionHash::HASH_GIT_COMMIT,
$commit['commit'],
);
$hashes[] = array(
ArcanistDifferentialRevisionHash::HASH_GIT_TREE,
$commit['tree'],
);
}
break;
case DifferentialRevisionControlSystem::MERCURIAL:
foreach ($data as $commit) {
$hashes[] = array(
ArcanistDifferentialRevisionHash::HASH_MERCURIAL_COMMIT,
$commit['rev'],
);
}
break;
}
$conn_w = $revision->establishConnection('w');
$sql = array();
foreach ($hashes as $info) {
list($type, $hash) = $info;
$sql[] = qsprintf(
$conn_w,
'(%d, %s, %s)',
$revision->getID(),
$type,
$hash);
}
queryfx(
$conn_w,
'DELETE FROM %T WHERE revisionID = %d',
ArcanistDifferentialRevisionHash::TABLE_NAME,
$revision->getID());
if ($sql) {
queryfx(
$conn_w,
'INSERT INTO %T (revisionID, type, hash) VALUES %LQ',
ArcanistDifferentialRevisionHash::TABLE_NAME,
$sql);
}
}
private function renderAffectedFilesForMail(DifferentialDiff $diff) {
$changesets = $diff->getChangesets();
$filenames = mpull($changesets, 'getDisplayFilename');
sort($filenames);
$count = count($filenames);
$max = 250;
if ($count > $max) {
$filenames = array_slice($filenames, 0, $max);
$filenames[] = pht('(%d more files...)', ($count - $max));
}
return implode("\n", $filenames);
}
private function renderPatchHTMLForMail($patch) {
return phutil_tag('pre',
array('style' => 'font-family: monospace;'), $patch);
}
private function buildPatchForMail(DifferentialDiff $diff, $byte_limit) {
$format = PhabricatorEnv::getEnvConfig('metamta.differential.patch-format');
return id(new DifferentialRawDiffRenderer())
->setViewer($this->getActor())
->setFormat($format)
->setChangesets($diff->getChangesets())
->setByteLimit($byte_limit)
->buildPatch();
}
protected function willPublish(PhabricatorLiskDAO $object, array $xactions) {
// Reload to pick up the active diff and reviewer status.
return id(new DifferentialRevisionQuery())
->setViewer($this->getActor())
->needReviewers(true)
->needActiveDiffs(true)
->withIDs(array($object->getID()))
->executeOne();
}
protected function getCustomWorkerState() {
return array(
'changedPriorToCommitURI' => $this->changedPriorToCommitURI,
'firstBroadcast' => $this->firstBroadcast,
'isDraftDemotion' => $this->isDraftDemotion,
);
}
protected function loadCustomWorkerState(array $state) {
$this->changedPriorToCommitURI = idx($state, 'changedPriorToCommitURI');
$this->firstBroadcast = idx($state, 'firstBroadcast');
$this->isDraftDemotion = idx($state, 'isDraftDemotion');
return $this;
}
private function newSwapReviewersTransaction(
DifferentialRevision $revision,
$new_author_phid) {
$old_author_phid = $revision->getAuthorPHID();
if ($old_author_phid === $new_author_phid) {
return;
}
// If the revision is changing authorship, add the previous author as a
// reviewer and remove the new author.
$edits = array(
'-' => array(
$new_author_phid,
),
'+' => array(
$old_author_phid,
),
);
// NOTE: We're setting setIsCommandeerSideEffect() on this because normally
// you can't add a revision's author as a reviewer, but this action swaps
// them after validation executes.
$xaction_type = DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE;
return id(new DifferentialTransaction())
->setTransactionType($xaction_type)
->setIgnoreOnNoEffect(true)
->setIsCommandeerSideEffect(true)
->setNewValue($edits);
}
public function getActiveDiff($object) {
if ($this->getIsNewObject()) {
return null;
} else {
return $object->getActiveDiff();
}
}
/**
* When a reviewer makes a comment, mark the last revision they commented
* on.
*
* This allows us to show a hint to help authors and other reviewers quickly
* distinguish between reviewers who have participated in the discussion and
* reviewers who haven't been part of it.
*/
private function markReviewerComments($object, array $xactions) {
$acting_phid = $this->getActingAsPHID();
if (!$acting_phid) {
return;
}
$diff = $this->getActiveDiff($object);
if (!$diff) {
return;
}
$has_comment = false;
foreach ($xactions as $xaction) {
if ($xaction->hasComment()) {
$has_comment = true;
break;
}
}
if (!$has_comment) {
return;
}
$reviewer_table = new DifferentialReviewer();
$conn = $reviewer_table->establishConnection('w');
queryfx(
$conn,
'UPDATE %T SET lastCommentDiffPHID = %s
WHERE revisionPHID = %s
AND reviewerPHID = %s',
$reviewer_table->getTableName(),
$diff->getPHID(),
$object->getPHID(),
$acting_phid);
}
private function loadUnbroadcastTransactions($object) {
$viewer = $this->requireActor();
$xactions = id(new DifferentialTransactionQuery())
->setViewer($viewer)
->withObjectPHIDs(array($object->getPHID()))
->execute();
return array_reverse($xactions);
}
protected function didApplyTransactions($object, array $xactions) {
// In a moment, we're going to try to publish draft revisions which have
// completed all their builds. However, we only want to do that if the
// actor is either the revision author or an omnipotent user (generally,
// the Harbormaster application).
// If we let any actor publish the revision as a side effect of other
// changes then an unlucky third party who innocently comments on the draft
// can end up racing Harbormaster and promoting the revision. At best, this
// is confusing. It can also run into validation problems with the "Request
// Review" transaction. See PHI309 for some discussion.
$author_phid = $object->getAuthorPHID();
$viewer = $this->requireActor();
$can_undraft =
($this->getActingAsPHID() === $author_phid) ||
($viewer->isOmnipotent());
// If a draft revision has no outstanding builds and we're automatically
// making drafts public after builds finish, make the revision public.
if ($can_undraft) {
$auto_undraft = !$object->getHoldAsDraft();
} else {
$auto_undraft = false;
}
$can_promote = false;
$can_demote = false;
// "Draft" revisions can promote to "Review Requested" after builds pass,
// or demote to "Changes Planned" after builds fail.
if ($object->isDraft()) {
$can_promote = true;
$can_demote = true;
}
// See PHI584. "Changes Planned" revisions which are not yet broadcasting
// can promote to "Review Requested" if builds pass.
// This pass is presumably the result of someone restarting the builds and
// having them work this time, perhaps because the builds are not perfectly
// reliable or perhaps because someone fixed some issue with build hardware
// or some other dependency.
// Currently, there's no legitimate way to end up in this state except
// through automatic demotion, so this behavior should not generate an
// undue level of confusion or ambiguity. Also note that these changes can
// not demote again since they've already been demoted once.
if ($object->isChangePlanned()) {
if (!$object->getShouldBroadcast()) {
$can_promote = true;
}
}
if (($can_promote || $can_demote) && $auto_undraft) {
$status = $this->loadCompletedBuildableStatus($object);
$is_passed = ($status === HarbormasterBuildableStatus::STATUS_PASSED);
$is_failed = ($status === HarbormasterBuildableStatus::STATUS_FAILED);
if ($is_passed && $can_promote) {
// When Harbormaster moves a revision out of the draft state, we
// attribute the action to the revision author since this is more
// natural and more useful.
// Additionally, we change the acting PHID for the transaction set
// to the author if it isn't already a user so that mail comes from
// the natural author.
$acting_phid = $this->getActingAsPHID();
$user_type = PhabricatorPeopleUserPHIDType::TYPECONST;
if (phid_get_type($acting_phid) != $user_type) {
$this->setActingAsPHID($author_phid);
}
$xaction = $object->getApplicationTransactionTemplate()
->setAuthorPHID($author_phid)
->setTransactionType(
DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE)
->setNewValue(true);
// If we're creating this revision and immediately moving it out of
// the draft state, mark this as a create transaction so it gets
// hidden in the timeline and mail, since it isn't interesting: it
// is as though the draft phase never happened.
if ($this->getIsNewObject()) {
$xaction->setIsCreateTransaction(true);
}
// Queue this transaction and apply it separately after the current
// batch of transactions finishes so that Herald can fire on the new
// revision state. See T13027 for discussion.
$this->queueTransaction($xaction);
} else if ($is_failed && $can_demote) {
// When demoting a revision, we act as "Harbormaster" instead of
// the author since this feels a little more natural.
$harbormaster_phid = id(new PhabricatorHarbormasterApplication())
->getPHID();
$xaction = $object->getApplicationTransactionTemplate()
->setAuthorPHID($harbormaster_phid)
->setMetadataValue('draft.demote', true)
->setTransactionType(
DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE)
->setNewValue(true);
$this->queueTransaction($xaction);
}
}
// If the revision is new or was a draft, and is no longer a draft, we
// might be sending the first email about it.
// This might mean it was created directly into a non-draft state, or
// it just automatically undrafted after builds finished, or a user
// explicitly promoted it out of the draft state with an action like
// "Request Review".
// If we haven't sent any email about it yet, mark this email as the first
// email so the mail gets enriched with "SUMMARY" and "TEST PLAN".
$is_new = $this->getIsNewObject();
$was_broadcasting = $this->wasBroadcasting;
if ($object->getShouldBroadcast()) {
if (!$was_broadcasting || $is_new) {
// Mark this as the first broadcast we're sending about the revision
// so mail can generate specially.
$this->firstBroadcast = true;
}
}
return $xactions;
}
private function loadCompletedBuildableStatus(
DifferentialRevision $revision) {
$viewer = $this->requireActor();
$builds = $revision->loadImpactfulBuilds($viewer);
return $revision->newBuildableStatusForBuilds($builds);
}
private function requireReviewers(DifferentialRevision $revision) {
if ($revision->hasAttachedReviewers()) {
return;
}
$with_reviewers = id(new DifferentialRevisionQuery())
->setViewer($this->getActor())
->needReviewers(true)
->withPHIDs(array($revision->getPHID()))
->executeOne();
if (!$with_reviewers) {
throw new Exception(
pht(
'Failed to reload revision ("%s").',
$revision->getPHID()));
}
$revision->attachReviewers($with_reviewers->getReviewers());
}
}
diff --git a/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php b/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php
index 966b306580..767cef9553 100644
--- a/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php
+++ b/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php
@@ -1,64 +1,64 @@
<?php
final class HeraldDifferentialDiffAdapter extends HeraldDifferentialAdapter {
public function getAdapterApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function initializeNewAdapter() {
$this->setDiff(new DifferentialDiff());
}
public function isSingleEventAdapter() {
return true;
}
protected function loadChangesets() {
return $this->loadChangesetsWithHunks();
}
protected function loadChangesetsWithHunks() {
return $this->getDiff()->getChangesets();
}
public function getObject() {
return $this->getDiff();
}
public function getAdapterContentType() {
return 'differential.diff';
}
public function getAdapterContentName() {
return pht('Differential Diffs');
}
public function getAdapterContentDescription() {
return pht(
"React to new diffs being uploaded, before writes occur.\n".
"These rules can reject diffs before they are written to permanent ".
"storage, to prevent users from accidentally uploading private keys or ".
"other sensitive information.");
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
default:
return false;
}
}
public function getHeraldName() {
return pht('New Diff');
}
public function supportsWebhooks() {
return false;
}
}
diff --git a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
index 858a42dbc9..1ac6a33c28 100644
--- a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
+++ b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
@@ -1,158 +1,158 @@
<?php
final class HeraldDifferentialRevisionAdapter
extends HeraldDifferentialAdapter
implements HarbormasterBuildableAdapterInterface {
protected $revision;
protected $affectedPackages;
protected $changesets;
private $haveHunks;
private $buildRequests = array();
public function getAdapterApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function newObject() {
return new DifferentialRevision();
}
public function isTestAdapterForObject($object) {
return ($object instanceof DifferentialRevision);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when a revision is created or updated.');
}
public function newTestAdapter(PhabricatorUser $viewer, $object) {
return self::newLegacyAdapter(
$object,
$object->loadActiveDiff());
}
protected function initializeNewAdapter() {
$this->revision = $this->newObject();
}
public function getObject() {
return $this->revision;
}
public function getAdapterContentType() {
return 'differential';
}
public function getAdapterContentName() {
return pht('Differential Revisions');
}
public function getAdapterContentDescription() {
return pht(
"React to revisions being created or updated.\n".
"Revision rules can send email, flag revisions, add reviewers, ".
"and run build plans.");
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public static function newLegacyAdapter(
DifferentialRevision $revision,
DifferentialDiff $diff) {
$object = new HeraldDifferentialRevisionAdapter();
// Reload the revision to pick up relationship information.
$revision = id(new DifferentialRevisionQuery())
->withIDs(array($revision->getID()))
->setViewer(PhabricatorUser::getOmnipotentUser())
->needReviewers(true)
->executeOne();
$object->revision = $revision;
$object->setDiff($diff);
return $object;
}
public function getHeraldName() {
return $this->revision->getTitle();
}
protected function loadChangesets() {
if ($this->changesets === null) {
$this->changesets = $this->getDiff()->loadChangesets();
}
return $this->changesets;
}
protected function loadChangesetsWithHunks() {
$changesets = $this->loadChangesets();
if ($changesets && !$this->haveHunks) {
$this->haveHunks = true;
id(new DifferentialHunkQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withChangesets($changesets)
->needAttachToChangesets(true)
->execute();
}
return $changesets;
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$this->affectedPackages = array();
$repository = $this->loadRepository();
if ($repository) {
$packages = PhabricatorOwnersPackage::loadAffectedPackagesForChangesets(
$repository,
$this->getDiff(),
$this->loadChangesets());
$this->affectedPackages = $packages;
}
}
return $this->affectedPackages;
}
public function loadReviewers() {
return $this->getObject()->getReviewerPHIDs();
}
/* -( HarbormasterBuildableAdapterInterface )------------------------------ */
public function getHarbormasterBuildablePHID() {
return $this->getDiff()->getPHID();
}
public function getHarbormasterContainerPHID() {
return $this->getObject()->getPHID();
}
public function getQueuedHarbormasterBuildRequests() {
return $this->buildRequests;
}
public function queueHarbormasterBuildRequest(
HarbormasterBuildRequest $request) {
$this->buildRequests[] = $request;
}
}
diff --git a/src/applications/differential/phid/DifferentialChangesetPHIDType.php b/src/applications/differential/phid/DifferentialChangesetPHIDType.php
index c558c0a6a2..357d787cdf 100644
--- a/src/applications/differential/phid/DifferentialChangesetPHIDType.php
+++ b/src/applications/differential/phid/DifferentialChangesetPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class DifferentialChangesetPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DCNG';
public function getTypeName() {
return pht('Differential Changeset');
}
public function newObject() {
return new DifferentialChangeset();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DifferentialChangesetQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$changeset = $objects[$phid];
$id = $changeset->getID();
$handle->setName(pht('Changeset %d', $id));
}
}
}
diff --git a/src/applications/differential/phid/DifferentialDiffPHIDType.php b/src/applications/differential/phid/DifferentialDiffPHIDType.php
index 746da368c7..494f87f598 100644
--- a/src/applications/differential/phid/DifferentialDiffPHIDType.php
+++ b/src/applications/differential/phid/DifferentialDiffPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class DifferentialDiffPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DIFF';
public function getTypeName() {
return pht('Differential Diff');
}
public function newObject() {
return new DifferentialDiff();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DifferentialDiffQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$diff = $objects[$phid];
$id = $diff->getID();
$handle->setName(pht('Diff %d', $id));
$handle->setURI("/differential/diff/{$id}/");
}
}
}
diff --git a/src/applications/differential/phid/DifferentialRevisionPHIDType.php b/src/applications/differential/phid/DifferentialRevisionPHIDType.php
index a7d3c9f4a7..b54d4a624f 100644
--- a/src/applications/differential/phid/DifferentialRevisionPHIDType.php
+++ b/src/applications/differential/phid/DifferentialRevisionPHIDType.php
@@ -1,79 +1,79 @@
<?php
final class DifferentialRevisionPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DREV';
public function getTypeName() {
return pht('Differential Revision');
}
public function newObject() {
return new DifferentialRevision();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DifferentialRevisionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$revision = $objects[$phid];
$title = $revision->getTitle();
$monogram = $revision->getMonogram();
$uri = $revision->getURI();
$handle
->setName($monogram)
->setURI($uri)
->setFullName("{$monogram}: {$title}");
if ($revision->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^D[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new DifferentialRevisionQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/differential/query/DifferentialChangesetQuery.php b/src/applications/differential/query/DifferentialChangesetQuery.php
index ee29aa1cf8..99176c28d4 100644
--- a/src/applications/differential/query/DifferentialChangesetQuery.php
+++ b/src/applications/differential/query/DifferentialChangesetQuery.php
@@ -1,178 +1,178 @@
<?php
final class DifferentialChangesetQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $diffPHIDs;
private $diffs;
private $needAttachToDiffs;
private $needHunks;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDiffs(array $diffs) {
assert_instances_of($diffs, 'DifferentialDiff');
$this->diffs = $diffs;
return $this;
}
public function withDiffPHIDs(array $phids) {
$this->diffPHIDs = $phids;
return $this;
}
public function needAttachToDiffs($attach) {
$this->needAttachToDiffs = $attach;
return $this;
}
public function needHunks($need) {
$this->needHunks = $need;
return $this;
}
protected function willExecute() {
// If we fail to load any changesets (which is possible in the case of an
// empty commit) we'll never call didFilterPage(). Attach empty changeset
// lists now so that we end up with the right result.
if ($this->needAttachToDiffs) {
foreach ($this->diffs as $diff) {
$diff->attachChangesets(array());
}
}
}
public function newResultObject() {
return new DifferentialChangeset();
}
protected function willFilterPage(array $changesets) {
// First, attach all the diffs we already have. We can just do this
// directly without worrying about querying for them. When we don't have
// a diff, record that we need to load it.
if ($this->diffs) {
$have_diffs = mpull($this->diffs, null, 'getID');
} else {
$have_diffs = array();
}
$must_load = array();
foreach ($changesets as $key => $changeset) {
$diff_id = $changeset->getDiffID();
if (isset($have_diffs[$diff_id])) {
$changeset->attachDiff($have_diffs[$diff_id]);
} else {
$must_load[$key] = $changeset;
}
}
// Load all the diffs we don't have.
$need_diff_ids = mpull($must_load, 'getDiffID');
$more_diffs = array();
if ($need_diff_ids) {
$more_diffs = id(new DifferentialDiffQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withIDs($need_diff_ids)
->execute();
$more_diffs = mpull($more_diffs, null, 'getID');
}
// Attach the diffs we loaded.
foreach ($must_load as $key => $changeset) {
$diff_id = $changeset->getDiffID();
if (isset($more_diffs[$diff_id])) {
$changeset->attachDiff($more_diffs[$diff_id]);
} else {
// We didn't have the diff, and could not load it (it does not exist,
// or we can't see it), so filter this result out.
unset($changesets[$key]);
}
}
return $changesets;
}
protected function didFilterPage(array $changesets) {
if ($this->needAttachToDiffs) {
$changeset_groups = mgroup($changesets, 'getDiffID');
foreach ($this->diffs as $diff) {
$diff_changesets = idx($changeset_groups, $diff->getID(), array());
$diff->attachChangesets($diff_changesets);
}
}
if ($this->needHunks) {
id(new DifferentialHunkQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withChangesets($changesets)
->needAttachToChangesets(true)
->execute();
}
return $changesets;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->diffs !== null) {
$where[] = qsprintf(
$conn,
'diffID IN (%Ld)',
mpull($this->diffs, 'getID'));
}
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->diffPHIDs !== null) {
$diff_ids = queryfx_all(
$conn,
'SELECT id FROM %R WHERE phid IN (%Ls)',
new DifferentialDiff(),
$this->diffPHIDs);
$diff_ids = ipull($diff_ids, 'id', null);
if (!$diff_ids) {
throw new PhabricatorEmptyQueryException();
}
$where[] = qsprintf(
$conn,
'diffID IN (%Ld)',
$diff_ids);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
}
diff --git a/src/applications/differential/query/DifferentialChangesetSearchEngine.php b/src/applications/differential/query/DifferentialChangesetSearchEngine.php
index b6279ec339..f3235443e9 100644
--- a/src/applications/differential/query/DifferentialChangesetSearchEngine.php
+++ b/src/applications/differential/query/DifferentialChangesetSearchEngine.php
@@ -1,149 +1,149 @@
<?php
final class DifferentialChangesetSearchEngine
extends PhabricatorApplicationSearchEngine {
private $diff;
public function setDiff(DifferentialDiff $diff) {
$this->diff = $diff;
return $this;
}
public function getDiff() {
return $this->diff;
}
public function getResultTypeDescription() {
return pht('Differential Changesets');
}
public function getApplicationClassName() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
$query = id(new DifferentialChangesetQuery());
if ($this->diff) {
$query->withDiffs(array($this->diff));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['diffPHIDs']) {
$query->withDiffPHIDs($map['diffPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Diffs'))
->setKey('diffPHIDs')
->setAliases(array('diff', 'diffs', 'diffPHID'))
->setDescription(
pht('Find changesets attached to a particular diff.')),
);
}
protected function getURI($path) {
$diff = $this->getDiff();
if ($diff) {
return '/differential/diff/'.$diff->getID().'/changesets/'.$path;
}
throw new PhutilMethodNotImplementedException();
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All Changesets');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'all':
return $query->setParameter('order', 'oldest');
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $changesets,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($changesets, 'DifferentialChangeset');
$viewer = $this->requireViewer();
$rows = array();
foreach ($changesets as $changeset) {
$link = phutil_tag(
'a',
array(
'href' => '/differential/changeset/?ref='.$changeset->getID(),
),
$changeset->getDisplayFilename());
$type = $changeset->getChangeType();
$title = DifferentialChangeType::getFullNameForChangeType($type);
$add_lines = $changeset->getAddLines();
if (!$add_lines) {
$add_lines = null;
} else {
$add_lines = '+'.$add_lines;
}
$rem_lines = $changeset->getDelLines();
if (!$rem_lines) {
$rem_lines = null;
} else {
$rem_lines = '-'.$rem_lines;
}
$rows[] = array(
$changeset->newFileTreeIcon(),
$title,
$link,
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
null,
pht('Change'),
pht('Path'),
))
->setColumnClasses(
array(
null,
null,
'pri wide',
));
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
}
diff --git a/src/applications/differential/query/DifferentialDiffQuery.php b/src/applications/differential/query/DifferentialDiffQuery.php
index 04019df1e0..552a467898 100644
--- a/src/applications/differential/query/DifferentialDiffQuery.php
+++ b/src/applications/differential/query/DifferentialDiffQuery.php
@@ -1,191 +1,191 @@
<?php
final class DifferentialDiffQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $revisionIDs;
private $revisionPHIDs;
private $commitPHIDs;
private $hasRevision;
private $needChangesets = false;
private $needProperties;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRevisionIDs(array $revision_ids) {
$this->revisionIDs = $revision_ids;
return $this;
}
public function withRevisionPHIDs(array $revision_phids) {
$this->revisionPHIDs = $revision_phids;
return $this;
}
public function withCommitPHIDs(array $phids) {
$this->commitPHIDs = $phids;
return $this;
}
public function withHasRevision($has_revision) {
$this->hasRevision = $has_revision;
return $this;
}
public function needChangesets($bool) {
$this->needChangesets = $bool;
return $this;
}
public function needProperties($need_properties) {
$this->needProperties = $need_properties;
return $this;
}
public function newResultObject() {
return new DifferentialDiff();
}
protected function willFilterPage(array $diffs) {
$revision_ids = array_filter(mpull($diffs, 'getRevisionID'));
$revisions = array();
if ($revision_ids) {
$revisions = id(new DifferentialRevisionQuery())
->setViewer($this->getViewer())
->withIDs($revision_ids)
->execute();
}
foreach ($diffs as $key => $diff) {
if (!$diff->getRevisionID()) {
continue;
}
$revision = idx($revisions, $diff->getRevisionID());
if ($revision) {
$diff->attachRevision($revision);
continue;
}
unset($diffs[$key]);
}
if ($diffs && $this->needChangesets) {
$diffs = $this->loadChangesets($diffs);
}
return $diffs;
}
protected function didFilterPage(array $diffs) {
if ($this->needProperties) {
$properties = id(new DifferentialDiffProperty())->loadAllWhere(
'diffID IN (%Ld)',
mpull($diffs, 'getID'));
$properties = mgroup($properties, 'getDiffID');
foreach ($diffs as $diff) {
$map = idx($properties, $diff->getID(), array());
$map = mpull($map, 'getData', 'getName');
$diff->attachDiffProperties($map);
}
}
return $diffs;
}
private function loadChangesets(array $diffs) {
id(new DifferentialChangesetQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withDiffs($diffs)
->needAttachToDiffs(true)
->needHunks(true)
->execute();
return $diffs;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->revisionIDs !== null) {
$where[] = qsprintf(
$conn,
'revisionID IN (%Ld)',
$this->revisionIDs);
}
if ($this->commitPHIDs !== null) {
$where[] = qsprintf(
$conn,
'commitPHID IN (%Ls)',
$this->commitPHIDs);
}
if ($this->hasRevision !== null) {
if ($this->hasRevision) {
$where[] = qsprintf(
$conn,
'revisionID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'revisionID IS NULL');
}
}
if ($this->revisionPHIDs !== null) {
$viewer = $this->getViewer();
$revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->setParentQuery($this)
->withPHIDs($this->revisionPHIDs)
->execute();
$revision_ids = mpull($revisions, 'getID');
if (!$revision_ids) {
throw new PhabricatorEmptyQueryException();
}
$where[] = qsprintf(
$conn,
'revisionID IN (%Ls)',
$revision_ids);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
}
diff --git a/src/applications/differential/query/DifferentialDiffSearchEngine.php b/src/applications/differential/query/DifferentialDiffSearchEngine.php
index 89feeb5c3e..31393d4681 100644
--- a/src/applications/differential/query/DifferentialDiffSearchEngine.php
+++ b/src/applications/differential/query/DifferentialDiffSearchEngine.php
@@ -1,79 +1,79 @@
<?php
final class DifferentialDiffSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Differential Diffs');
}
public function getApplicationClassName() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function newQuery() {
return new DifferentialDiffQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['revisionPHIDs']) {
$query->withRevisionPHIDs($map['revisionPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Revisions'))
->setKey('revisionPHIDs')
->setAliases(array('revision', 'revisions', 'revisionPHID'))
->setDescription(
pht('Find diffs attached to a particular revision.')),
);
}
protected function getURI($path) {
return '/differential/diff/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All Diffs');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $revisions,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($revisions, 'DifferentialDiff');
$viewer = $this->requireViewer();
// NOTE: This is only exposed to Conduit, so we don't currently render
// results.
return id(new PhabricatorApplicationSearchResultView());
}
}
diff --git a/src/applications/differential/query/DifferentialHunkQuery.php b/src/applications/differential/query/DifferentialHunkQuery.php
index 21787f04e5..3b07676aa8 100644
--- a/src/applications/differential/query/DifferentialHunkQuery.php
+++ b/src/applications/differential/query/DifferentialHunkQuery.php
@@ -1,89 +1,89 @@
<?php
final class DifferentialHunkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $changesets;
private $shouldAttachToChangesets;
public function withChangesets(array $changesets) {
assert_instances_of($changesets, 'DifferentialChangeset');
$this->changesets = $changesets;
return $this;
}
public function needAttachToChangesets($attach) {
$this->shouldAttachToChangesets = $attach;
return $this;
}
protected function willExecute() {
// If we fail to load any hunks at all (for example, because all of
// the requested changesets are directories or empty files and have no
// hunks) we'll never call didFilterPage(), and thus never have an
// opportunity to attach hunks. Attach empty hunk lists now so that we
// end up with the right result.
if ($this->shouldAttachToChangesets) {
foreach ($this->changesets as $changeset) {
$changeset->attachHunks(array());
}
}
}
public function newResultObject() {
return new DifferentialHunk();
}
protected function willFilterPage(array $hunks) {
$changesets = mpull($this->changesets, null, 'getID');
foreach ($hunks as $key => $hunk) {
$changeset = idx($changesets, $hunk->getChangesetID());
if (!$changeset) {
unset($hunks[$key]);
}
$hunk->attachChangeset($changeset);
}
return $hunks;
}
protected function didFilterPage(array $hunks) {
if ($this->shouldAttachToChangesets) {
$hunk_groups = mgroup($hunks, 'getChangesetID');
foreach ($this->changesets as $changeset) {
$hunks = idx($hunk_groups, $changeset->getID(), array());
$changeset->attachHunks($hunks);
}
}
return $hunks;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if (!$this->changesets) {
throw new Exception(
pht(
'You must load hunks via changesets, with %s!',
'withChangesets()'));
}
$where[] = qsprintf(
$conn,
'changesetID IN (%Ld)',
mpull($this->changesets, 'getID'));
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function getDefaultOrderVector() {
// TODO: Do we need this?
return array('-id');
}
}
diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php
index 75d3e052e4..d6b249cac5 100644
--- a/src/applications/differential/query/DifferentialRevisionQuery.php
+++ b/src/applications/differential/query/DifferentialRevisionQuery.php
@@ -1,1091 +1,1091 @@
<?php
/**
* @task config Query Configuration
* @task exec Query Execution
* @task internal Internals
*/
final class DifferentialRevisionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $authors = array();
private $draftAuthors = array();
private $ccs = array();
private $reviewers = array();
private $revIDs = array();
private $commitHashes = array();
private $phids = array();
private $responsibles = array();
private $branches = array();
private $repositoryPHIDs;
private $updatedEpochMin;
private $updatedEpochMax;
private $statuses;
private $isOpen;
private $createdEpochMin;
private $createdEpochMax;
private $noReviewers;
private $paths;
const ORDER_MODIFIED = 'order-modified';
const ORDER_CREATED = 'order-created';
private $needActiveDiffs = false;
private $needDiffIDs = false;
private $needCommitPHIDs = false;
private $needHashes = false;
private $needReviewers = false;
private $needReviewerAuthority;
private $needDrafts;
private $needFlags;
/* -( Query Configuration )------------------------------------------------ */
/**
* Find revisions affecting one or more items in a list of paths.
*
* @param list<string> List of file paths.
* @return this
* @task config
*/
public function withPaths(array $paths) {
$this->paths = $paths;
return $this;
}
/**
* Filter results to revisions authored by one of the given PHIDs. Calling
* this function will clear anything set by previous calls to
* @{method:withAuthors}.
*
* @param array List of PHIDs of authors
* @return this
* @task config
*/
public function withAuthors(array $author_phids) {
$this->authors = $author_phids;
return $this;
}
/**
* Filter results to revisions which CC one of the listed people. Calling this
* function will clear anything set by previous calls to @{method:withCCs}.
*
* @param array List of PHIDs of subscribers.
* @return this
* @task config
*/
public function withCCs(array $cc_phids) {
$this->ccs = $cc_phids;
return $this;
}
/**
* Filter results to revisions that have one of the provided PHIDs as
* reviewers. Calling this function will clear anything set by previous calls
* to @{method:withReviewers}.
*
* @param array List of PHIDs of reviewers
* @return this
* @task config
*/
public function withReviewers(array $reviewer_phids) {
if ($reviewer_phids === array()) {
throw new Exception(
pht(
'Empty "withReviewers()" constraint is invalid. Provide one or '.
'more values, or remove the constraint.'));
}
$with_none = false;
foreach ($reviewer_phids as $key => $phid) {
switch ($phid) {
case DifferentialNoReviewersDatasource::FUNCTION_TOKEN:
$with_none = true;
unset($reviewer_phids[$key]);
break;
default:
break;
}
}
$this->noReviewers = $with_none;
if ($reviewer_phids) {
$this->reviewers = array_values($reviewer_phids);
}
return $this;
}
/**
* Filter results to revisions that have one of the provided commit hashes.
* Calling this function will clear anything set by previous calls to
* @{method:withCommitHashes}.
*
* @param array List of pairs <Class
* ArcanistDifferentialRevisionHash::HASH_$type constant,
* hash>
* @return this
* @task config
*/
public function withCommitHashes(array $commit_hashes) {
$this->commitHashes = $commit_hashes;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withIsOpen($is_open) {
$this->isOpen = $is_open;
return $this;
}
/**
* Filter results to revisions on given branches.
*
* @param list List of branch names.
* @return this
* @task config
*/
public function withBranches(array $branches) {
$this->branches = $branches;
return $this;
}
/**
* Filter results to only return revisions whose ids are in the given set.
*
* @param array List of revision ids
* @return this
* @task config
*/
public function withIDs(array $ids) {
$this->revIDs = $ids;
return $this;
}
/**
* Filter results to only return revisions whose PHIDs are in the given set.
*
* @param array List of revision PHIDs
* @return this
* @task config
*/
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
/**
* Given a set of users, filter results to return only revisions they are
* responsible for (i.e., they are either authors or reviewers).
*
* @param array List of user PHIDs.
* @return this
* @task config
*/
public function withResponsibleUsers(array $responsible_phids) {
$this->responsibles = $responsible_phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withUpdatedEpochBetween($min, $max) {
$this->updatedEpochMin = $min;
$this->updatedEpochMax = $max;
return $this;
}
public function withCreatedEpochBetween($min, $max) {
$this->createdEpochMin = $min;
$this->createdEpochMax = $max;
return $this;
}
/**
* Set whether or not the query should load the active diff for each
* revision.
*
* @param bool True to load and attach diffs.
* @return this
* @task config
*/
public function needActiveDiffs($need_active_diffs) {
$this->needActiveDiffs = $need_active_diffs;
return $this;
}
/**
* Set whether or not the query should load the associated commit PHIDs for
* each revision.
*
* @param bool True to load and attach diffs.
* @return this
* @task config
*/
public function needCommitPHIDs($need_commit_phids) {
$this->needCommitPHIDs = $need_commit_phids;
return $this;
}
/**
* Set whether or not the query should load associated diff IDs for each
* revision.
*
* @param bool True to load and attach diff IDs.
* @return this
* @task config
*/
public function needDiffIDs($need_diff_ids) {
$this->needDiffIDs = $need_diff_ids;
return $this;
}
/**
* Set whether or not the query should load associated commit hashes for each
* revision.
*
* @param bool True to load and attach commit hashes.
* @return this
* @task config
*/
public function needHashes($need_hashes) {
$this->needHashes = $need_hashes;
return $this;
}
/**
* Set whether or not the query should load associated reviewers.
*
* @param bool True to load and attach reviewers.
* @return this
* @task config
*/
public function needReviewers($need_reviewers) {
$this->needReviewers = $need_reviewers;
return $this;
}
/**
* Request information about the viewer's authority to act on behalf of each
* reviewer. In particular, they have authority to act on behalf of projects
* they are a member of.
*
* @param bool True to load and attach authority.
* @return this
* @task config
*/
public function needReviewerAuthority($need_reviewer_authority) {
$this->needReviewerAuthority = $need_reviewer_authority;
return $this;
}
public function needFlags($need_flags) {
$this->needFlags = $need_flags;
return $this;
}
public function needDrafts($need_drafts) {
$this->needDrafts = $need_drafts;
return $this;
}
/* -( Query Execution )---------------------------------------------------- */
public function newResultObject() {
return new DifferentialRevision();
}
/**
* Execute the query as configured, returning matching
* @{class:DifferentialRevision} objects.
*
* @return list List of matching DifferentialRevision objects.
* @task exec
*/
protected function loadPage() {
$data = $this->loadData();
$data = $this->didLoadRawRows($data);
$table = $this->newResultObject();
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $revisions) {
$viewer = $this->getViewer();
$repository_phids = mpull($revisions, 'getRepositoryPHID');
$repository_phids = array_filter($repository_phids);
$repositories = array();
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
}
// If a revision is associated with a repository:
//
// - the viewer must be able to see the repository; or
// - the viewer must have an automatic view capability.
//
// In the latter case, we'll load the revision but not load the repository.
$can_view = PhabricatorPolicyCapability::CAN_VIEW;
foreach ($revisions as $key => $revision) {
$repo_phid = $revision->getRepositoryPHID();
if (!$repo_phid) {
// The revision has no associated repository. Attach `null` and move on.
$revision->attachRepository(null);
continue;
}
$repository = idx($repositories, $repo_phid);
if ($repository) {
// The revision has an associated repository, and the viewer can see
// it. Attach it and move on.
$revision->attachRepository($repository);
continue;
}
if ($revision->hasAutomaticCapability($can_view, $viewer)) {
// The revision has an associated repository which the viewer can not
// see, but the viewer has an automatic capability on this revision.
// Load the revision without attaching a repository.
$revision->attachRepository(null);
continue;
}
if ($this->getViewer()->isOmnipotent()) {
// The viewer is omnipotent. Allow the revision to load even without
// a repository.
$revision->attachRepository(null);
continue;
}
// The revision has an associated repository, and the viewer can't see
// it, and the viewer has no special capabilities. Filter out this
// revision.
$this->didRejectResult($revision);
unset($revisions[$key]);
}
if (!$revisions) {
return array();
}
$table = new DifferentialRevision();
$conn_r = $table->establishConnection('r');
if ($this->needCommitPHIDs) {
$this->loadCommitPHIDs($revisions);
}
$need_active = $this->needActiveDiffs;
$need_ids = $need_active || $this->needDiffIDs;
if ($need_ids) {
$this->loadDiffIDs($conn_r, $revisions);
}
if ($need_active) {
$this->loadActiveDiffs($conn_r, $revisions);
}
if ($this->needHashes) {
$this->loadHashes($conn_r, $revisions);
}
if ($this->needReviewers || $this->needReviewerAuthority) {
$this->loadReviewers($conn_r, $revisions);
}
return $revisions;
}
protected function didFilterPage(array $revisions) {
$viewer = $this->getViewer();
if ($this->needFlags) {
$flags = id(new PhabricatorFlagQuery())
->setViewer($viewer)
->withOwnerPHIDs(array($viewer->getPHID()))
->withObjectPHIDs(mpull($revisions, 'getPHID'))
->execute();
$flags = mpull($flags, null, 'getObjectPHID');
foreach ($revisions as $revision) {
$revision->attachFlag(
$viewer,
idx($flags, $revision->getPHID()));
}
}
if ($this->needDrafts) {
PhabricatorDraftEngine::attachDrafts(
$viewer,
$revisions);
}
return $revisions;
}
private function loadData() {
$table = $this->newResultObject();
$conn = $table->establishConnection('r');
$selects = array();
// NOTE: If the query includes "responsiblePHIDs", we execute it as a
// UNION of revisions they own and revisions they're reviewing. This has
// much better performance than doing it with JOIN/WHERE.
if ($this->responsibles) {
$basic_authors = $this->authors;
$basic_reviewers = $this->reviewers;
try {
// Build the query where the responsible users are authors.
$this->authors = array_merge($basic_authors, $this->responsibles);
$this->reviewers = $basic_reviewers;
$selects[] = $this->buildSelectStatement($conn);
// Build the query where the responsible users are reviewers, or
// projects they are members of are reviewers.
$this->authors = $basic_authors;
$this->reviewers = array_merge($basic_reviewers, $this->responsibles);
$selects[] = $this->buildSelectStatement($conn);
// Put everything back like it was.
$this->authors = $basic_authors;
$this->reviewers = $basic_reviewers;
} catch (Exception $ex) {
$this->authors = $basic_authors;
$this->reviewers = $basic_reviewers;
throw $ex;
}
} else {
$selects[] = $this->buildSelectStatement($conn);
}
if (count($selects) > 1) {
$unions = null;
foreach ($selects as $select) {
if (!$unions) {
$unions = $select;
continue;
}
$unions = qsprintf(
$conn,
'%Q UNION DISTINCT %Q',
$unions,
$select);
}
$query = qsprintf(
$conn,
'%Q %Q %Q',
$unions,
$this->buildOrderClause($conn, true),
$this->buildLimitClause($conn));
} else {
$query = head($selects);
}
return queryfx_all($conn, '%Q', $query);
}
private function buildSelectStatement(AphrontDatabaseConnection $conn_r) {
$table = new DifferentialRevision();
$select = $this->buildSelectClause($conn_r);
$from = qsprintf(
$conn_r,
'FROM %T r',
$table->getTableName());
$joins = $this->buildJoinsClause($conn_r);
$where = $this->buildWhereClause($conn_r);
$group_by = $this->buildGroupClause($conn_r);
$having = $this->buildHavingClause($conn_r);
$order_by = $this->buildOrderClause($conn_r);
$limit = $this->buildLimitClause($conn_r);
return qsprintf(
$conn_r,
'(%Q %Q %Q %Q %Q %Q %Q %Q)',
$select,
$from,
$joins,
$where,
$group_by,
$having,
$order_by,
$limit);
}
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
private function buildJoinsClause(AphrontDatabaseConnection $conn) {
$joins = array();
if ($this->paths) {
$path_table = new DifferentialAffectedPath();
$joins[] = qsprintf(
$conn,
'JOIN %R paths ON paths.revisionID = r.id',
$path_table);
}
if ($this->commitHashes) {
$joins[] = qsprintf(
$conn,
'JOIN %T hash_rel ON hash_rel.revisionID = r.id',
ArcanistDifferentialRevisionHash::TABLE_NAME);
}
if ($this->ccs) {
$joins[] = qsprintf(
$conn,
'JOIN %T e_ccs ON e_ccs.src = r.phid '.
'AND e_ccs.type = %s '.
'AND e_ccs.dst in (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasSubscriberEdgeType::EDGECONST,
$this->ccs);
}
if ($this->reviewers) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T reviewer ON reviewer.revisionPHID = r.phid
AND reviewer.reviewerStatus != %s
AND reviewer.reviewerPHID in (%Ls)',
id(new DifferentialReviewer())->getTableName(),
DifferentialReviewerStatus::STATUS_RESIGNED,
$this->reviewers);
}
if ($this->noReviewers) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T no_reviewer ON no_reviewer.revisionPHID = r.phid
AND no_reviewer.reviewerStatus != %s',
id(new DifferentialReviewer())->getTableName(),
DifferentialReviewerStatus::STATUS_RESIGNED);
}
if ($this->draftAuthors) {
$joins[] = qsprintf(
$conn,
'JOIN %T has_draft ON has_draft.srcPHID = r.phid
AND has_draft.type = %s
AND has_draft.dstPHID IN (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasDraftEdgeType::EDGECONST,
$this->draftAuthors);
}
$joins[] = $this->buildJoinClauseParts($conn);
return $this->formatJoinClause($conn, $joins);
}
/**
* @task internal
*/
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$viewer = $this->getViewer();
$where = array();
if ($this->paths !== null) {
$paths = $this->paths;
$path_map = id(new DiffusionPathIDQuery($paths))
->loadPathIDs();
if (!$path_map) {
// If none of the paths have entries in the PathID table, we can not
// possibly find any revisions affecting them.
throw new PhabricatorEmptyQueryException();
}
$where[] = qsprintf(
$conn,
'paths.pathID IN (%Ld)',
array_fuse($path_map));
// If we have repository PHIDs, additionally constrain this query to
// try to help MySQL execute it efficiently.
if ($this->repositoryPHIDs !== null) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->setParentQuery($this)
->withPHIDs($this->repositoryPHIDs)
->execute();
if (!$repositories) {
throw new PhabricatorEmptyQueryException();
}
$repository_ids = mpull($repositories, 'getID');
$where[] = qsprintf(
$conn,
'paths.repositoryID IN (%Ld)',
$repository_ids);
}
}
if ($this->authors) {
$where[] = qsprintf(
$conn,
'r.authorPHID IN (%Ls)',
$this->authors);
}
if ($this->revIDs) {
$where[] = qsprintf(
$conn,
'r.id IN (%Ld)',
$this->revIDs);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn,
'r.repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->commitHashes) {
$hash_clauses = array();
foreach ($this->commitHashes as $info) {
list($type, $hash) = $info;
$hash_clauses[] = qsprintf(
$conn,
'(hash_rel.type = %s AND hash_rel.hash = %s)',
$type,
$hash);
}
$hash_clauses = qsprintf($conn, '%LO', $hash_clauses);
$where[] = $hash_clauses;
}
if ($this->phids) {
$where[] = qsprintf(
$conn,
'r.phid IN (%Ls)',
$this->phids);
}
if ($this->branches) {
$where[] = qsprintf(
$conn,
'r.branchName in (%Ls)',
$this->branches);
}
if ($this->updatedEpochMin !== null) {
$where[] = qsprintf(
$conn,
'r.dateModified >= %d',
$this->updatedEpochMin);
}
if ($this->updatedEpochMax !== null) {
$where[] = qsprintf(
$conn,
'r.dateModified <= %d',
$this->updatedEpochMax);
}
if ($this->createdEpochMin !== null) {
$where[] = qsprintf(
$conn,
'r.dateCreated >= %d',
$this->createdEpochMin);
}
if ($this->createdEpochMax !== null) {
$where[] = qsprintf(
$conn,
'r.dateCreated <= %d',
$this->createdEpochMax);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'r.status in (%Ls)',
$this->statuses);
}
if ($this->isOpen !== null) {
if ($this->isOpen) {
$statuses = DifferentialLegacyQuery::getModernValues(
DifferentialLegacyQuery::STATUS_OPEN);
} else {
$statuses = DifferentialLegacyQuery::getModernValues(
DifferentialLegacyQuery::STATUS_CLOSED);
}
$where[] = qsprintf(
$conn,
'r.status in (%Ls)',
$statuses);
}
$reviewer_subclauses = array();
if ($this->noReviewers) {
$reviewer_subclauses[] = qsprintf(
$conn,
'no_reviewer.reviewerPHID IS NULL');
}
if ($this->reviewers) {
$reviewer_subclauses[] = qsprintf(
$conn,
'reviewer.reviewerPHID IS NOT NULL');
}
if ($reviewer_subclauses) {
$where[] = qsprintf($conn, '%LO', $reviewer_subclauses);
}
$where[] = $this->buildWhereClauseParts($conn);
return $this->formatWhereClause($conn, $where);
}
/**
* @task internal
*/
protected function shouldGroupQueryResultRows() {
if ($this->paths) {
// (If we have exactly one repository and exactly one path, we don't
// technically need to group, but it's simpler to always group.)
return true;
}
if (count($this->ccs) > 1) {
return true;
}
if (count($this->reviewers) > 1) {
return true;
}
if (count($this->commitHashes) > 1) {
return true;
}
if ($this->noReviewers) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
public function getBuiltinOrders() {
$orders = parent::getBuiltinOrders() + array(
'updated' => array(
'vector' => array('updated', 'id'),
'name' => pht('Date Updated (Latest First)'),
'aliases' => array(self::ORDER_MODIFIED),
),
'outdated' => array(
'vector' => array('-updated', '-id'),
'name' => pht('Date Updated (Oldest First)'),
),
);
// Alias the "newest" builtin to the historical key for it.
$orders['newest']['aliases'][] = self::ORDER_CREATED;
return $orders;
}
protected function getDefaultOrderVector() {
return array('updated', 'id');
}
public function getOrderableColumns() {
return array(
'updated' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'dateModified',
'type' => 'int',
),
) + parent::getOrderableColumns();
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'updated' => (int)$object->getDateModified(),
);
}
private function loadCommitPHIDs(array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
if (!$revisions) {
return;
}
$revisions = mpull($revisions, null, 'getPHID');
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($revisions))
->withEdgeTypes(
array(
DifferentialRevisionHasCommitEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($revisions as $phid => $revision) {
$commit_phids = $edge_query->getDestinationPHIDs(array($phid));
$revision->attachCommitPHIDs($commit_phids);
}
}
private function loadDiffIDs($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$diff_table = new DifferentialDiff();
$diff_ids = queryfx_all(
$conn_r,
'SELECT revisionID, id FROM %T WHERE revisionID IN (%Ld)
ORDER BY id DESC',
$diff_table->getTableName(),
mpull($revisions, 'getID'));
$diff_ids = igroup($diff_ids, 'revisionID');
foreach ($revisions as $revision) {
$ids = idx($diff_ids, $revision->getID(), array());
$ids = ipull($ids, 'id');
$revision->attachDiffIDs($ids);
}
}
private function loadActiveDiffs($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$diff_table = new DifferentialDiff();
$load_ids = array();
foreach ($revisions as $revision) {
$diffs = $revision->getDiffIDs();
if ($diffs) {
$load_ids[] = max($diffs);
}
}
$active_diffs = array();
if ($load_ids) {
$active_diffs = $diff_table->loadAllWhere(
'id IN (%Ld)',
$load_ids);
}
$active_diffs = mpull($active_diffs, null, 'getRevisionID');
foreach ($revisions as $revision) {
$revision->attachActiveDiff(idx($active_diffs, $revision->getID()));
}
}
private function loadHashes(
AphrontDatabaseConnection $conn_r,
array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE revisionID IN (%Ld)',
'differential_revisionhash',
mpull($revisions, 'getID'));
$data = igroup($data, 'revisionID');
foreach ($revisions as $revision) {
$hashes = idx($data, $revision->getID(), array());
$list = array();
foreach ($hashes as $hash) {
$list[] = array($hash['type'], $hash['hash']);
}
$revision->attachHashes($list);
}
}
private function loadReviewers(
AphrontDatabaseConnection $conn,
array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$reviewer_table = new DifferentialReviewer();
$reviewer_rows = queryfx_all(
$conn,
'SELECT * FROM %T WHERE revisionPHID IN (%Ls)
ORDER BY id ASC',
$reviewer_table->getTableName(),
mpull($revisions, 'getPHID'));
$reviewer_list = $reviewer_table->loadAllFromArray($reviewer_rows);
$reviewer_map = mgroup($reviewer_list, 'getRevisionPHID');
foreach ($reviewer_map as $key => $reviewers) {
$reviewer_map[$key] = mpull($reviewers, null, 'getReviewerPHID');
}
$viewer = $this->getViewer();
$viewer_phid = $viewer->getPHID();
$allow_key = 'differential.allow-self-accept';
$allow_self = PhabricatorEnv::getEnvConfig($allow_key);
// Figure out which of these reviewers the viewer has authority to act as.
if ($this->needReviewerAuthority && $viewer_phid) {
$authority = $this->loadReviewerAuthority(
$revisions,
$reviewer_map,
$allow_self);
}
foreach ($revisions as $revision) {
$reviewers = idx($reviewer_map, $revision->getPHID(), array());
foreach ($reviewers as $reviewer_phid => $reviewer) {
if ($this->needReviewerAuthority) {
if (!$viewer_phid) {
// Logged-out users never have authority.
$has_authority = false;
} else if ((!$allow_self) &&
($revision->getAuthorPHID() == $viewer_phid)) {
// The author can never have authority unless we allow self-accept.
$has_authority = false;
} else {
// Otherwise, look up whether the viewer has authority.
$has_authority = isset($authority[$reviewer_phid]);
}
$reviewer->attachAuthority($viewer, $has_authority);
}
$reviewers[$reviewer_phid] = $reviewer;
}
$revision->attachReviewers($reviewers);
}
}
private function loadReviewerAuthority(
array $revisions,
array $reviewers,
$allow_self) {
$revision_map = mpull($revisions, null, 'getPHID');
$viewer_phid = $this->getViewer()->getPHID();
// Find all the project/package reviewers which the user may have authority
// over.
$project_phids = array();
$package_phids = array();
$project_type = PhabricatorProjectProjectPHIDType::TYPECONST;
$package_type = PhabricatorOwnersPackagePHIDType::TYPECONST;
foreach ($reviewers as $revision_phid => $reviewer_list) {
if (!$allow_self) {
if ($revision_map[$revision_phid]->getAuthorPHID() == $viewer_phid) {
// If self-review isn't permitted, the user will never have
// authority over projects on revisions they authored because you
// can't accept your own revisions, so we don't need to load any
// data about these reviewers.
continue;
}
}
foreach ($reviewer_list as $reviewer_phid => $reviewer) {
$phid_type = phid_get_type($reviewer_phid);
if ($phid_type == $project_type) {
$project_phids[] = $reviewer_phid;
}
if ($phid_type == $package_type) {
$package_phids[] = $reviewer_phid;
}
}
}
// The viewer has authority over themselves.
$user_authority = array_fuse(array($viewer_phid));
// And over any projects they are a member of.
$project_authority = array();
if ($project_phids) {
$project_authority = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->withMemberPHIDs(array($viewer_phid))
->execute();
$project_authority = mpull($project_authority, 'getPHID');
$project_authority = array_fuse($project_authority);
}
// And over any packages they own.
$package_authority = array();
if ($package_phids) {
$package_authority = id(new PhabricatorOwnersPackageQuery())
->setViewer($this->getViewer())
->withPHIDs($package_phids)
->withAuthorityPHIDs(array($viewer_phid))
->execute();
$package_authority = mpull($package_authority, 'getPHID');
$package_authority = array_fuse($package_authority);
}
return $user_authority + $project_authority + $package_authority;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function getPrimaryTableAlias() {
return 'r';
}
}
diff --git a/src/applications/differential/query/DifferentialRevisionSearchEngine.php b/src/applications/differential/query/DifferentialRevisionSearchEngine.php
index 1ec5265630..b69b764bb8 100644
--- a/src/applications/differential/query/DifferentialRevisionSearchEngine.php
+++ b/src/applications/differential/query/DifferentialRevisionSearchEngine.php
@@ -1,393 +1,393 @@
<?php
final class DifferentialRevisionSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Differential Revisions');
}
public function getApplicationClassName() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
protected function newResultBuckets() {
return DifferentialRevisionResultBucket::getAllResultBuckets();
}
public function newQuery() {
return id(new DifferentialRevisionQuery())
->needFlags(true)
->needDrafts(true)
->needReviewers(true);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['responsiblePHIDs']) {
$query->withResponsibleUsers($map['responsiblePHIDs']);
}
if ($map['authorPHIDs']) {
$query->withAuthors($map['authorPHIDs']);
}
if ($map['reviewerPHIDs']) {
$query->withReviewers($map['reviewerPHIDs']);
}
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['createdStart'] || $map['createdEnd']) {
$query->withCreatedEpochBetween(
$map['createdStart'],
$map['createdEnd']);
}
if ($map['modifiedStart'] || $map['modifiedEnd']) {
$query->withUpdatedEpochBetween(
$map['modifiedStart'],
$map['modifiedEnd']);
}
if ($map['affectedPaths']) {
$query->withPaths($map['affectedPaths']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Responsible Users'))
->setKey('responsiblePHIDs')
->setAliases(array('responsiblePHID', 'responsibles', 'responsible'))
->setDatasource(new DifferentialResponsibleDatasource())
->setDescription(
pht('Find revisions that a given user is responsible for.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors', 'authorPHID'))
->setDescription(
pht('Find revisions with specific authors.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Reviewers'))
->setKey('reviewerPHIDs')
->setAliases(array('reviewer', 'reviewers', 'reviewerPHID'))
->setDatasource(new DifferentialReviewerFunctionDatasource())
->setDescription(
pht('Find revisions with specific reviewers.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setDatasource(new DiffusionRepositoryFunctionDatasource())
->setDescription(
pht('Find revisions from specific repositories.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setAliases(array('status'))
->setDatasource(new DifferentialRevisionStatusFunctionDatasource())
->setDescription(
pht('Find revisions with particular statuses.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart')
->setDescription(
pht('Find revisions created at or after a particular time.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd')
->setDescription(
pht('Find revisions created at or before a particular time.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Modified After'))
->setKey('modifiedStart')
->setIsHidden(true)
->setDescription(
pht('Find revisions modified at or after a particular time.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Modified Before'))
->setKey('modifiedEnd')
->setIsHidden(true)
->setDescription(
pht('Find revisions modified at or before a particular time.')),
id(new PhabricatorSearchStringListField())
->setKey('affectedPaths')
->setLabel(pht('Affected Paths'))
->setDescription(
pht('Search for revisions affecting particular paths.'))
->setIsHidden(true),
);
}
protected function getURI($path) {
return '/differential/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['active'] = pht('Active Revisions');
$names['authored'] = pht('Authored');
}
$names['all'] = pht('All Revisions');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'active':
$bucket_key = DifferentialRevisionRequiredActionResultBucket::BUCKETKEY;
return $query
->setParameter('responsiblePHIDs', array($viewer->getPHID()))
->setParameter('statuses', array('open()'))
->setParameter('bucket', $bucket_key);
case 'authored':
return $query
->setParameter('authorPHIDs', array($viewer->getPHID()));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
DifferentialLegacyQuery::STATUS_ANY => pht('All'),
DifferentialLegacyQuery::STATUS_OPEN => pht('Open'),
DifferentialLegacyQuery::STATUS_ACCEPTED => pht('Accepted'),
DifferentialLegacyQuery::STATUS_NEEDS_REVIEW => pht('Needs Review'),
DifferentialLegacyQuery::STATUS_NEEDS_REVISION => pht('Needs Revision'),
DifferentialLegacyQuery::STATUS_CLOSED => pht('Closed'),
DifferentialLegacyQuery::STATUS_ABANDONED => pht('Abandoned'),
);
}
protected function renderResultList(
array $revisions,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($revisions, 'DifferentialRevision');
$viewer = $this->requireViewer();
$template = id(new DifferentialRevisionListView())
->setViewer($viewer)
->setNoBox($this->isPanelContext());
$bucket = $this->getResultBucket($query);
$unlanded = $this->loadUnlandedDependencies($revisions);
$views = array();
if ($bucket) {
$bucket->setViewer($viewer);
try {
$groups = $bucket->newResultGroups($query, $revisions);
foreach ($groups as $group) {
// Don't show groups in Dashboard Panels
if ($group->getObjects() || !$this->isPanelContext()) {
$views[] = id(clone $template)
->setHeader($group->getName())
->setNoDataString($group->getNoDataString())
->setRevisions($group->getObjects());
}
}
} catch (Exception $ex) {
$this->addError($ex->getMessage());
}
} else {
$views[] = id(clone $template)
->setRevisions($revisions);
}
if (!$views) {
$views[] = id(new DifferentialRevisionListView())
->setViewer($viewer)
->setNoDataString(pht('No revisions found.'));
}
foreach ($views as $view) {
$view->setUnlandedDependencies($unlanded);
}
if (count($views) == 1) {
// Reduce this to a PHUIObjectItemListView so we can get the free
// support from ApplicationSearch.
$list = head($views)->render();
} else {
$list = $views;
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($list);
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Diff'))
->setHref('/differential/diff/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Pre-commit code review. Revisions that are waiting on your input '.
'will appear here.'))
->addAction($create_button);
return $view;
}
private function loadUnlandedDependencies(array $revisions) {
$phids = array();
foreach ($revisions as $revision) {
if (!$revision->isAccepted()) {
continue;
}
$phids[] = $revision->getPHID();
}
if (!$phids) {
return array();
}
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($phids)
->withEdgeTypes(
array(
DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST,
));
$query->execute();
$revision_phids = $query->getDestinationPHIDs();
if (!$revision_phids) {
return array();
}
$viewer = $this->requireViewer();
$blocking_revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withPHIDs($revision_phids)
->withIsOpen(true)
->execute();
$blocking_revisions = mpull($blocking_revisions, null, 'getPHID');
$result = array();
foreach ($revisions as $revision) {
$revision_phid = $revision->getPHID();
$blocking_phids = $query->getDestinationPHIDs(array($revision_phid));
$blocking = array_select_keys($blocking_revisions, $blocking_phids);
if ($blocking) {
$result[$revision_phid] = $blocking;
}
}
return $result;
}
protected function newExportFields() {
$fields = array(
id(new PhabricatorStringExportField())
->setKey('monogram')
->setLabel(pht('Monogram')),
id(new PhabricatorPHIDExportField())
->setKey('authorPHID')
->setLabel(pht('Author PHID')),
id(new PhabricatorStringExportField())
->setKey('author')
->setLabel(pht('Author')),
id(new PhabricatorStringExportField())
->setKey('status')
->setLabel(pht('Status')),
id(new PhabricatorStringExportField())
->setKey('statusName')
->setLabel(pht('Status Name')),
id(new PhabricatorURIExportField())
->setKey('uri')
->setLabel(pht('URI')),
id(new PhabricatorStringExportField())
->setKey('title')
->setLabel(pht('Title')),
id(new PhabricatorStringExportField())
->setKey('summary')
->setLabel(pht('Summary')),
id(new PhabricatorStringExportField())
->setKey('testPlan')
->setLabel(pht('Test Plan')),
);
return $fields;
}
protected function newExportData(array $revisions) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($revisions as $revision) {
$phids[] = $revision->getAuthorPHID();
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($revisions as $revision) {
$author_phid = $revision->getAuthorPHID();
if ($author_phid) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = null;
}
$status = $revision->getStatusObject();
$status_name = $status->getDisplayName();
$status_value = $status->getKey();
$export[] = array(
'monogram' => $revision->getMonogram(),
'authorPHID' => $author_phid,
'author' => $author_name,
'status' => $status_value,
'statusName' => $status_name,
'uri' => PhabricatorEnv::getProductionURI($revision->getURI()),
'title' => (string)$revision->getTitle(),
'summary' => (string)$revision->getSummary(),
'testPlan' => (string)$revision->getTestPlan(),
);
}
return $export;
}
}
diff --git a/src/applications/differential/query/DifferentialViewStateQuery.php b/src/applications/differential/query/DifferentialViewStateQuery.php
index 604a6de1db..19104748d3 100644
--- a/src/applications/differential/query/DifferentialViewStateQuery.php
+++ b/src/applications/differential/query/DifferentialViewStateQuery.php
@@ -1,60 +1,60 @@
<?php
final class DifferentialViewStateQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $viewerPHIDs;
private $objectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withViewerPHIDs(array $phids) {
$this->viewerPHIDs = $phids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new DifferentialViewState();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->viewerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'viewerPHID IN (%Ls)',
$this->viewerPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
}
diff --git a/src/applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php b/src/applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php
index bea7056ea2..e06693dc22 100644
--- a/src/applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php
@@ -1,128 +1,128 @@
<?php
final class DifferentialBlockingReviewerDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Blocking Reviewers');
}
public function getPlaceholderText() {
return pht('Type a user, project, or package name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'blocking' => array(
'name' => pht('Blocking: ...'),
'arguments' => pht('reviewer'),
'summary' => pht('Select a blocking reviewer.'),
'description' => pht(
"This function allows you to add a reviewer as a blocking ".
"reviewer. For example, this will add `%s` as a blocking reviewer: ".
"\n\n%s\n\n",
'alincoln',
'> blocking(alincoln)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setColor('red')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setPHID('blocking('.$result->getPHID().')')
->setDisplayName(pht('Blocking: %s', $result->getDisplayName()))
->setName($result->getName().' blocking');
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$results = array();
foreach ($phids as $phid) {
$results[] = array(
'type' => DifferentialReviewerStatus::STATUS_BLOCKING,
'phid' => $phid,
);
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht('Blocking: Invalid Reviewer'));
} else {
$token
->setIcon('fa-asterisk')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setColor('red')
->setKey('blocking('.$token->getKey().')')
->setValue(pht('Blocking: %s', $token->getValue()));
}
}
return $tokens;
}
private function resolvePHIDs(array $phids) {
$usernames = array();
foreach ($phids as $key => $phid) {
if (phid_get_type($phid) != PhabricatorPeopleUserPHIDType::TYPECONST) {
$usernames[$key] = $phid;
}
}
if ($usernames) {
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withUsernames($usernames)
->execute();
$users = mpull($users, null, 'getUsername');
foreach ($usernames as $key => $username) {
$user = idx($users, $username);
if ($user) {
$phids[$key] = $user->getPHID();
}
}
}
return $phids;
}
}
diff --git a/src/applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php b/src/applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php
index 8ad8274ea3..bdb109fce9 100644
--- a/src/applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php
@@ -1,115 +1,115 @@
<?php
final class DifferentialExactUserFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Users');
}
public function getPlaceholderText() {
return pht('Type exact(<user>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'exact' => array(
'name' => pht('Exact: ...'),
'arguments' => pht('username'),
'summary' => pht('Find results matching users exactly.'),
'description' => pht(
"This function allows you to find results associated only with ".
"a user, exactly, and not any of their projects or packages. For ".
"example, this will find results associated with only `%s`:".
"\n\n%s\n\n",
'alincoln',
'> exact(alincoln)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setColor(null)
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setPHID('exact('.$result->getPHID().')')
->setDisplayName(pht('Exact User: %s', $result->getDisplayName()))
->setName($result->getName().' exact');
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
return $this->resolvePHIDs($phids);
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht('Exact User: Invalid User'));
} else {
$token
->setIcon('fa-asterisk')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setKey('exact('.$token->getKey().')')
->setValue(pht('Exact User: %s', $token->getValue()));
}
}
return $tokens;
}
private function resolvePHIDs(array $phids) {
$usernames = array();
foreach ($phids as $key => $phid) {
if (phid_get_type($phid) != PhabricatorPeopleUserPHIDType::TYPECONST) {
$usernames[$key] = $phid;
}
}
if ($usernames) {
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withUsernames($usernames)
->execute();
$users = mpull($users, null, 'getUsername');
foreach ($usernames as $key => $username) {
$user = idx($users, $username);
if ($user) {
$phids[$key] = $user->getPHID();
}
}
}
return $phids;
}
}
diff --git a/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php b/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php
index 083b6c7cb5..eeff6de538 100644
--- a/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialNoReviewersDatasource.php
@@ -1,78 +1,78 @@
<?php
final class DifferentialNoReviewersDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'none()';
public function getBrowseTitle() {
return pht('Browse No Reviewers');
}
public function getPlaceholderText() {
return pht('Type "none"...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getDatasourceFunctions() {
return array(
'none' => array(
'name' => pht('No Reviewers'),
'summary' => pht('Find results which have no reviewers.'),
'description' => pht(
"This function includes results which have no reviewers. Use a ".
"query like this to find results with no reviewers:\n\n%s\n\n".
"If you combine this function with other functions, the query will ".
"return results which match the other selectors //or// have no ".
"reviewers. For example, this query will find results which have ".
"`alincoln` as a reviewer, and will also find results which have ".
"no reviewers:".
"\n\n%s",
'> none()',
'> alincoln, none()'),
),
);
}
public function loadResults() {
$results = array(
$this->buildNoReviewersResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = self::FUNCTION_TOKEN;
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildNoReviewersResult());
}
return $results;
}
private function buildNoReviewersResult() {
$name = pht('No Reviewers');
return $this->newFunctionResult()
->setName($name.' none')
->setDisplayName($name)
->setIcon('fa-ban')
->setPHID('none()')
->setUnique(true)
->addAttribute(pht('Select results with no reviewers.'));
}
}
diff --git a/src/applications/differential/typeahead/DifferentialResponsibleDatasource.php b/src/applications/differential/typeahead/DifferentialResponsibleDatasource.php
index 5307ab1866..4bca119347 100644
--- a/src/applications/differential/typeahead/DifferentialResponsibleDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialResponsibleDatasource.php
@@ -1,63 +1,63 @@
<?php
final class DifferentialResponsibleDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Responsible Users');
}
public function getPlaceholderText() {
return pht('Type a user, project, or package name, or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new DifferentialResponsibleUserDatasource(),
new DifferentialResponsibleViewerFunctionDatasource(),
new DifferentialExactUserFunctionDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
);
}
public static function expandResponsibleUsers(
PhabricatorUser $viewer,
array $values) {
$phids = array();
foreach ($values as $value) {
if (phid_get_type($value) == PhabricatorPeopleUserPHIDType::TYPECONST) {
$phids[] = $value;
}
}
if (!$phids) {
return $values;
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs($phids)
->execute();
foreach ($projects as $project) {
$phids[] = $project->getPHID();
$values[] = $project->getPHID();
}
$packages = id(new PhabricatorOwnersPackageQuery())
->setViewer($viewer)
->withOwnerPHIDs($phids)
->execute();
foreach ($packages as $package) {
$values[] = $package->getPHID();
}
return $values;
}
}
diff --git a/src/applications/differential/typeahead/DifferentialResponsibleUserDatasource.php b/src/applications/differential/typeahead/DifferentialResponsibleUserDatasource.php
index 8ac7b36520..494bca5f62 100644
--- a/src/applications/differential/typeahead/DifferentialResponsibleUserDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialResponsibleUserDatasource.php
@@ -1,30 +1,30 @@
<?php
final class DifferentialResponsibleUserDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Users');
}
public function getPlaceholderText() {
return pht('Type a user name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
protected function evaluateValues(array $values) {
return DifferentialResponsibleDatasource::expandResponsibleUsers(
$this->getViewer(),
$values);
}
}
diff --git a/src/applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php b/src/applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php
index d23ecff47d..05ae39ec2e 100644
--- a/src/applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php
@@ -1,77 +1,77 @@
<?php
final class DifferentialResponsibleViewerFunctionDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Viewer');
}
public function getPlaceholderText() {
return pht('Type viewer()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'viewer' => array(
'name' => pht('Current Viewer'),
'summary' => pht('Use the current viewing user.'),
'description' => pht(
'Show revisions the current viewer is responsible for. This '.
'function includes revisions the viewer is responsible for through '.
'membership in projects and packages.'),
),
);
}
public function loadResults() {
if ($this->getViewer()->getPHID()) {
$results = array($this->renderViewerFunctionToken());
} else {
$results = array();
}
return $this->filterResultsAgainstTokens($results);
}
protected function canEvaluateFunction($function) {
if (!$this->getViewer()->getPHID()) {
return false;
}
return parent::canEvaluateFunction($function);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = $this->getViewer()->getPHID();
}
return DifferentialResponsibleDatasource::expandResponsibleUsers(
$this->getViewer(),
$results);
}
public function renderFunctionTokens($function, array $argv_list) {
$tokens = array();
foreach ($argv_list as $argv) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->renderViewerFunctionToken());
}
return $tokens;
}
private function renderViewerFunctionToken() {
return $this->newFunctionResult()
->setName(pht('Current Viewer'))
->setPHID('viewer()')
->setIcon('fa-user')
->setUnique(true);
}
}
diff --git a/src/applications/differential/typeahead/DifferentialReviewerDatasource.php b/src/applications/differential/typeahead/DifferentialReviewerDatasource.php
index 18aa9e48b7..9030213404 100644
--- a/src/applications/differential/typeahead/DifferentialReviewerDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialReviewerDatasource.php
@@ -1,27 +1,27 @@
<?php
final class DifferentialReviewerDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Reviewers');
}
public function getPlaceholderText() {
return pht('Type a user, project, or package name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
new DifferentialBlockingReviewerDatasource(),
);
}
}
diff --git a/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php b/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php
index 3b79016055..ac185878c9 100644
--- a/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialReviewerFunctionDatasource.php
@@ -1,26 +1,26 @@
<?php
final class DifferentialReviewerFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Reviewers');
}
public function getPlaceholderText() {
return pht('Type a user, project, package name or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectOrUserFunctionDatasource(),
new PhabricatorOwnersPackageFunctionDatasource(),
new DifferentialNoReviewersDatasource(),
);
}
}
diff --git a/src/applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php b/src/applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php
index 8487111452..3c9e16a268 100644
--- a/src/applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php
@@ -1,74 +1,74 @@
<?php
final class DifferentialRevisionClosedStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'closed()';
public function getBrowseTitle() {
return pht('Browse Any Closed Status');
}
public function getPlaceholderText() {
return pht('Type closed()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getDatasourceFunctions() {
return array(
'closed' => array(
'name' => pht('Any Closed Status'),
'summary' => pht('Find results with any closed status.'),
'description' => pht(
'This function includes results which have any closed status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildClosedResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = DifferentialRevisionStatus::getAll();
foreach ($argv_list as $argv) {
foreach ($map as $status) {
if ($status->isClosedStatus()) {
$results[] = $status->getKey();
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildClosedResult());
}
return $results;
}
private function buildClosedResult() {
$name = pht('Any Closed Status');
return $this->newFunctionResult()
->setName($name.' closed')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any closed status.'));
}
}
diff --git a/src/applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.php b/src/applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.php
index 0f00e470c3..51da971918 100644
--- a/src/applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.php
@@ -1,74 +1,74 @@
<?php
final class DifferentialRevisionOpenStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'open()';
public function getBrowseTitle() {
return pht('Browse Any Open Status');
}
public function getPlaceholderText() {
return pht('Type open()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getDatasourceFunctions() {
return array(
'open' => array(
'name' => pht('Any Open Status'),
'summary' => pht('Find results with any open status.'),
'description' => pht(
'This function includes results which have any open status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildOpenResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = DifferentialRevisionStatus::getAll();
foreach ($argv_list as $argv) {
foreach ($map as $status) {
if (!$status->isClosedStatus()) {
$results[] = $status->getKey();
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildOpenResult());
}
return $results;
}
private function buildOpenResult() {
$name = pht('Any Open Status');
return $this->newFunctionResult()
->setName($name.' open')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any open status.'));
}
}
diff --git a/src/applications/differential/typeahead/DifferentialRevisionStatusDatasource.php b/src/applications/differential/typeahead/DifferentialRevisionStatusDatasource.php
index 5e240d3c29..978e9a847f 100644
--- a/src/applications/differential/typeahead/DifferentialRevisionStatusDatasource.php
+++ b/src/applications/differential/typeahead/DifferentialRevisionStatusDatasource.php
@@ -1,52 +1,52 @@
<?php
final class DifferentialRevisionStatusDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Statuses');
}
public function getPlaceholderText() {
return pht('Type a revision status name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$statuses = DifferentialRevisionStatus::getAll();
foreach ($statuses as $status) {
$key = $status->getKey();
$result = id(new PhabricatorTypeaheadResult())
->setIcon($status->getIcon())
->setPHID($key)
->setName($status->getDisplayName());
if ($status->isClosedStatus()) {
$result->addAttribute(pht('Closed Status'));
} else {
$result->addAttribute(pht('Open Status'));
}
$results[$key] = $result;
}
return $results;
}
}
diff --git a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
index 60a2667c95..02213cceee 100644
--- a/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
+++ b/src/applications/diffusion/editor/DiffusionCommitEditEngine.php
@@ -1,169 +1,169 @@
<?php
final class DiffusionCommitEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'diffusion.commit';
const ACTIONGROUP_AUDIT = 'audit';
const ACTIONGROUP_COMMIT = 'commit';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Commits');
}
public function getSummaryHeader() {
return pht('Edit Commits');
}
public function getSummaryText() {
return pht('Edit commits.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function newEditableObject() {
// NOTE: We must return a valid object here so that things like Conduit
// documentation generation work. You can't actually create commits via
// EditEngine. This is enforced with a "No One" creation policy.
$repository = new PhabricatorRepository();
$data = new PhabricatorRepositoryCommitData();
return id(new PhabricatorRepositoryCommit())
->attachRepository($repository)
->attachCommitData($data)
->attachAudits(array());
}
protected function newObjectQuery() {
$viewer = $this->getViewer();
return id(new DiffusionCommitQuery())
->needCommitData(true)
->needAuditRequests(true)
->needAuditAuthority(array($viewer))
->needIdentities(true);
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('commit/edit/');
}
protected function newCommentActionGroups() {
return array(
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_AUDIT)
->setLabel(pht('Audit Actions')),
id(new PhabricatorEditEngineCommentActionGroup())
->setKey(self::ACTIONGROUP_COMMIT)
->setLabel(pht('Commit Actions')),
);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Commit');
}
protected function getObjectCreateShortText() {
return pht('Create Commit');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Commit: %s', $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return $object->getDisplayName();
}
protected function getObjectName() {
return pht('Commit');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return PhabricatorPolicies::POLICY_NOONE;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$data = $object->getCommitData();
$fields = array();
$fields[] = id(new PhabricatorDatasourceEditField())
->setKey('auditors')
->setLabel(pht('Auditors'))
->setDatasource(new DiffusionAuditorDatasource())
->setUseEdgeTransactions(true)
->setTransactionType(
DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE)
->setCommentActionLabel(pht('Change Auditors'))
->setDescription(pht('Auditors for this commit.'))
->setConduitDescription(pht('Change the auditors for this commit.'))
->setConduitTypeDescription(pht('New auditors.'))
->setValue($object->getAuditorPHIDsForEdit());
$actions = DiffusionCommitActionTransaction::loadAllActions();
$actions = msortv($actions, 'getCommitActionOrderVector');
foreach ($actions as $key => $action) {
$fields[] = $action->newEditField($object, $viewer);
}
return $fields;
}
protected function newAutomaticCommentTransactions($object) {
$viewer = $this->getViewer();
$editor = $object->getApplicationTransactionEditor()
->setActor($viewer);
$xactions = $editor->newAutomaticInlineTransactions(
$object,
PhabricatorAuditActionConstants::INLINE,
new DiffusionDiffInlineCommentQuery());
return $xactions;
}
protected function newCommentPreviewContent($object, array $xactions) {
$viewer = $this->getViewer();
$type_inline = PhabricatorAuditActionConstants::INLINE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() === $type_inline) {
$inlines[] = $xaction->getComment();
}
}
$content = array();
if ($inlines) {
$inline_preview = id(new PHUIDiffInlineCommentPreviewListView())
->setViewer($viewer)
->setInlineComments($inlines);
$content[] = phutil_tag(
'div',
array(
'id' => 'inline-comment-preview',
),
$inline_preview);
}
return $content;
}
}
diff --git a/src/applications/diffusion/editor/DiffusionRepositoryEditEngine.php b/src/applications/diffusion/editor/DiffusionRepositoryEditEngine.php
index 07213afd2b..c9dbb2b329 100644
--- a/src/applications/diffusion/editor/DiffusionRepositoryEditEngine.php
+++ b/src/applications/diffusion/editor/DiffusionRepositoryEditEngine.php
@@ -1,525 +1,525 @@
<?php
final class DiffusionRepositoryEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'diffusion.repository';
private $versionControlSystem;
public function setVersionControlSystem($version_control_system) {
$this->versionControlSystem = $version_control_system;
return $this;
}
public function getVersionControlSystem() {
return $this->versionControlSystem;
}
public function isEngineConfigurable() {
return false;
}
public function isDefaultQuickCreateEngine() {
return true;
}
public function getQuickCreateOrderVector() {
return id(new PhutilSortVector())->addInt(300);
}
public function getEngineName() {
return pht('Repositories');
}
public function getSummaryHeader() {
return pht('Edit Repositories');
}
public function getSummaryText() {
return pht('Creates and edits repositories.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$repository = PhabricatorRepository::initializeNewRepository($viewer);
$repository->setDetail('newly-initialized', true);
$vcs = $this->getVersionControlSystem();
if ($vcs) {
$repository->setVersionControlSystem($vcs);
}
// Pick a random open service to allocate this repository on, if any exist.
// If there are no services, we aren't in cluster mode and will allocate
// locally. If there are services but none permit allocations, we fail.
// Eventually we can make this more flexible, but this rule is a reasonable
// starting point as we begin to deploy cluster services.
$services = id(new AlmanacServiceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withServiceTypes(
array(
AlmanacClusterRepositoryServiceType::SERVICETYPE,
))
->needProperties(true)
->execute();
if ($services) {
// Filter out services which do not permit new allocations.
foreach ($services as $key => $possible_service) {
if ($possible_service->getAlmanacPropertyValue('closed')) {
unset($services[$key]);
}
}
if (!$services) {
throw new Exception(
pht(
'This install is configured in cluster mode, but all available '.
'repository cluster services are closed to new allocations. '.
'At least one service must be open to allow new allocations to '.
'take place.'));
}
shuffle($services);
$service = head($services);
$repository->setAlmanacServicePHID($service->getPHID());
}
return $repository;
}
protected function newObjectQuery() {
return new PhabricatorRepositoryQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Repository');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Repository');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Repository: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getDisplayName();
}
protected function getObjectCreateShortText() {
return pht('Create Repository');
}
protected function getObjectName() {
return pht('Repository');
}
protected function getObjectViewURI($object) {
return $object->getPathURI('manage/');
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
DiffusionCreateRepositoriesCapability::CAPABILITY);
}
protected function newPages($object) {
$panels = DiffusionRepositoryManagementPanel::getAllPanels();
$pages = array();
$uris = array();
foreach ($panels as $panel_key => $panel) {
$panel->setRepository($object);
$uris[$panel_key] = $panel->getPanelURI();
$page = $panel->newEditEnginePage();
if (!$page) {
continue;
}
$pages[] = $page;
}
$basics_key = DiffusionRepositoryBasicsManagementPanel::PANELKEY;
$basics_uri = $uris[$basics_key];
$more_pages = array(
id(new PhabricatorEditPage())
->setKey('encoding')
->setLabel(pht('Text Encoding'))
->setViewURI($basics_uri)
->setFieldKeys(
array(
'encoding',
)),
id(new PhabricatorEditPage())
->setKey('extensions')
->setLabel(pht('Extensions'))
->setIsDefault(true),
);
foreach ($more_pages as $page) {
$pages[] = $page;
}
return $pages;
}
protected function willConfigureFields($object, array $fields) {
// Change the default field order so related fields are adjacent.
$after = array(
'policy.edit' => array('policy.push'),
);
$result = array();
foreach ($fields as $key => $value) {
$result[$key] = $value;
if (!isset($after[$key])) {
continue;
}
foreach ($after[$key] as $next_key) {
if (!isset($fields[$next_key])) {
continue;
}
unset($result[$next_key]);
$result[$next_key] = $fields[$next_key];
unset($fields[$next_key]);
}
}
return $result;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($object)
->execute();
$fetch_value = $object->getFetchRules();
$track_value = $object->getTrackOnlyRules();
$permanent_value = $object->getPermanentRefRules();
$automation_instructions = pht(
"Configure **Repository Automation** to allow this server to ".
"write to this repository.".
"\n\n".
"IMPORTANT: This feature is new, experimental, and not supported. ".
"Use it at your own risk.");
$staging_instructions = pht(
"To make it easier to run integration tests and builds on code ".
"under review, you can configure a **Staging Area**. When `arc` ".
"creates a diff, it will push a copy of the changes to the ".
"configured staging area with a corresponding tag.".
"\n\n".
"IMPORTANT: This feature is new, experimental, and not supported. ".
"Use it at your own risk.");
$subpath_instructions = pht(
'If you want to import only part of a repository, like `trunk/`, '.
'you can set a path in **Import Only**. The import process will ignore '.
'commits which do not affect this path.');
$filesize_warning = null;
if ($object->isGit()) {
$git_binary = PhutilBinaryAnalyzer::getForBinary('git');
$git_version = $git_binary->getBinaryVersion();
$filesize_version = '1.8.4';
if (version_compare($git_version, $filesize_version, '<')) {
$filesize_warning = pht(
'(WARNING) {icon exclamation-triangle} The version of "git" ("%s") '.
'installed on this server does not support '.
'"--batch-check=<format>", a feature required to enforce filesize '.
'limits. Upgrade to "git" %s or newer to use this feature.',
$git_version,
$filesize_version);
}
}
$track_instructions = pht(
'WARNING: The "Track Only" feature is deprecated. Use "Fetch Refs" '.
'and "Permanent Refs" instead. This feature will be removed in a '.
'future version of this software.');
return array(
id(new PhabricatorSelectEditField())
->setKey('vcs')
->setLabel(pht('Version Control System'))
->setTransactionType(
PhabricatorRepositoryVCSTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setIsCopyable(true)
->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes())
->setDescription(pht('Underlying repository version control system.'))
->setConduitDescription(
pht(
'Choose which version control system to use when creating a '.
'repository.'))
->setConduitTypeDescription(pht('Version control system selection.'))
->setValue($object->getVersionControlSystem()),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setIsRequired(true)
->setTransactionType(
PhabricatorRepositoryNameTransaction::TRANSACTIONTYPE)
->setDescription(pht('The repository name.'))
->setConduitDescription(pht('Rename the repository.'))
->setConduitTypeDescription(pht('New repository name.'))
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('callsign')
->setLabel(pht('Callsign'))
->setTransactionType(
PhabricatorRepositoryCallsignTransaction::TRANSACTIONTYPE)
->setDescription(pht('The repository callsign.'))
->setConduitDescription(pht('Change the repository callsign.'))
->setConduitTypeDescription(pht('New repository callsign.'))
->setValue($object->getCallsign()),
id(new PhabricatorTextEditField())
->setKey('shortName')
->setLabel(pht('Short Name'))
->setTransactionType(
PhabricatorRepositorySlugTransaction::TRANSACTIONTYPE)
->setDescription(pht('Short, unique repository name.'))
->setConduitDescription(pht('Change the repository short name.'))
->setConduitTypeDescription(pht('New short name for the repository.'))
->setValue($object->getRepositorySlug()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setTransactionType(
PhabricatorRepositoryDescriptionTransaction::TRANSACTIONTYPE)
->setDescription(pht('Repository description.'))
->setConduitDescription(pht('Change the repository description.'))
->setConduitTypeDescription(pht('New repository description.'))
->setValue($object->getDetail('description')),
id(new PhabricatorTextEditField())
->setKey('encoding')
->setLabel(pht('Text Encoding'))
->setIsCopyable(true)
->setTransactionType(
PhabricatorRepositoryEncodingTransaction::TRANSACTIONTYPE)
->setDescription(pht('Default text encoding.'))
->setConduitDescription(pht('Change the default text encoding.'))
->setConduitTypeDescription(pht('New text encoding.'))
->setValue($object->getDetail('encoding')),
id(new PhabricatorBoolEditField())
->setKey('allowDangerousChanges')
->setLabel(pht('Allow Dangerous Changes'))
->setIsCopyable(true)
->setIsFormField(false)
->setOptions(
pht('Prevent Dangerous Changes'),
pht('Allow Dangerous Changes'))
->setTransactionType(
PhabricatorRepositoryDangerousTransaction::TRANSACTIONTYPE)
->setDescription(pht('Permit dangerous changes to be made.'))
->setConduitDescription(pht('Allow or prevent dangerous changes.'))
->setConduitTypeDescription(pht('New protection setting.'))
->setValue($object->shouldAllowDangerousChanges()),
id(new PhabricatorBoolEditField())
->setKey('allowEnormousChanges')
->setLabel(pht('Allow Enormous Changes'))
->setIsCopyable(true)
->setIsFormField(false)
->setOptions(
pht('Prevent Enormous Changes'),
pht('Allow Enormous Changes'))
->setTransactionType(
PhabricatorRepositoryEnormousTransaction::TRANSACTIONTYPE)
->setDescription(pht('Permit enormous changes to be made.'))
->setConduitDescription(pht('Allow or prevent enormous changes.'))
->setConduitTypeDescription(pht('New protection setting.'))
->setValue($object->shouldAllowEnormousChanges()),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(
PhabricatorRepositoryActivateTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setOptions(PhabricatorRepository::getStatusNameMap())
->setDescription(pht('Active or inactive status.'))
->setConduitDescription(pht('Active or deactivate the repository.'))
->setConduitTypeDescription(pht('New repository status.'))
->setValue($object->getStatus()),
id(new PhabricatorTextEditField())
->setKey('defaultBranch')
->setLabel(pht('Default Branch'))
->setTransactionType(
PhabricatorRepositoryDefaultBranchTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Default branch name.'))
->setConduitDescription(pht('Set the default branch name.'))
->setConduitTypeDescription(pht('New default branch name.'))
->setValue($object->getDetail('default-branch')),
id(new PhabricatorTextAreaEditField())
->setIsStringList(true)
->setKey('fetchRefs')
->setLabel(pht('Fetch Refs'))
->setTransactionType(
PhabricatorRepositoryFetchRefsTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Fetch only these refs.'))
->setConduitDescription(pht('Set the fetched refs.'))
->setConduitTypeDescription(pht('New fetched refs.'))
->setValue($fetch_value),
id(new PhabricatorTextAreaEditField())
->setIsStringList(true)
->setKey('permanentRefs')
->setLabel(pht('Permanent Refs'))
->setTransactionType(
PhabricatorRepositoryPermanentRefsTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Only these refs are considered permanent.'))
->setConduitDescription(pht('Set the permanent refs.'))
->setConduitTypeDescription(pht('New permanent ref rules.'))
->setValue($permanent_value),
id(new PhabricatorTextAreaEditField())
->setIsStringList(true)
->setKey('trackOnly')
->setLabel(pht('Track Only'))
->setTransactionType(
PhabricatorRepositoryTrackOnlyTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setControlInstructions($track_instructions)
->setDescription(pht('Track only these branches.'))
->setConduitDescription(pht('Set the tracked branches.'))
->setConduitTypeDescription(pht('New tracked branches.'))
->setValue($track_value),
id(new PhabricatorTextEditField())
->setKey('importOnly')
->setLabel(pht('Import Only'))
->setTransactionType(
PhabricatorRepositorySVNSubpathTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Subpath to selectively import.'))
->setConduitDescription(pht('Set the subpath to import.'))
->setConduitTypeDescription(pht('New subpath to import.'))
->setValue($object->getDetail('svn-subpath'))
->setControlInstructions($subpath_instructions),
id(new PhabricatorTextEditField())
->setKey('stagingAreaURI')
->setLabel(pht('Staging Area URI'))
->setTransactionType(
PhabricatorRepositoryStagingURITransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(pht('Staging area URI.'))
->setConduitDescription(pht('Set the staging area URI.'))
->setConduitTypeDescription(pht('New staging area URI.'))
->setValue($object->getStagingURI())
->setControlInstructions($staging_instructions),
id(new PhabricatorDatasourceEditField())
->setKey('automationBlueprintPHIDs')
->setLabel(pht('Use Blueprints'))
->setTransactionType(
PhabricatorRepositoryBlueprintsTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDatasource(new DrydockBlueprintDatasource())
->setDescription(pht('Automation blueprints.'))
->setConduitDescription(pht('Change automation blueprints.'))
->setConduitTypeDescription(pht('New blueprint PHIDs.'))
->setValue($object->getAutomationBlueprintPHIDs())
->setControlInstructions($automation_instructions),
id(new PhabricatorStringListEditField())
->setKey('symbolLanguages')
->setLabel(pht('Languages'))
->setTransactionType(
PhabricatorRepositorySymbolLanguagesTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDescription(
pht('Languages which define symbols in this repository.'))
->setConduitDescription(
pht('Change symbol languages for this repository.'))
->setConduitTypeDescription(
pht('New symbol languages.'))
->setValue($object->getSymbolLanguages()),
id(new PhabricatorDatasourceEditField())
->setKey('symbolRepositoryPHIDs')
->setLabel(pht('Uses Symbols From'))
->setTransactionType(
PhabricatorRepositorySymbolSourcesTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setDatasource(new DiffusionRepositoryDatasource())
->setDescription(pht('Repositories to link symbols from.'))
->setConduitDescription(pht('Change symbol source repositories.'))
->setConduitTypeDescription(pht('New symbol repositories.'))
->setValue($object->getSymbolSources()),
id(new PhabricatorBoolEditField())
->setKey('publish')
->setLabel(pht('Publish/Notify'))
->setTransactionType(
PhabricatorRepositoryNotifyTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setOptions(
pht('Disable Notifications, Feed, and Herald'),
pht('Enable Notifications, Feed, and Herald'))
->setDescription(pht('Configure how changes are published.'))
->setConduitDescription(pht('Change publishing options.'))
->setConduitTypeDescription(pht('New notification setting.'))
->setValue(!$object->isPublishingDisabled()),
id(new PhabricatorPolicyEditField())
->setKey('policy.push')
->setLabel(pht('Push Policy'))
->setAliases(array('push'))
->setIsCopyable(true)
->setCapability(DiffusionPushCapability::CAPABILITY)
->setPolicies($policies)
->setTransactionType(
PhabricatorRepositoryPushPolicyTransaction::TRANSACTIONTYPE)
->setDescription(
pht('Controls who can push changes to the repository.'))
->setConduitDescription(
pht('Change the push policy of the repository.'))
->setConduitTypeDescription(pht('New policy PHID or constant.'))
->setValue($object->getPolicy(DiffusionPushCapability::CAPABILITY)),
id(new PhabricatorTextEditField())
->setKey('filesizeLimit')
->setLabel(pht('Filesize Limit'))
->setTransactionType(
PhabricatorRepositoryFilesizeLimitTransaction::TRANSACTIONTYPE)
->setDescription(pht('Maximum permitted file size.'))
->setConduitDescription(pht('Change the filesize limit.'))
->setConduitTypeDescription(pht('New repository filesize limit.'))
->setControlInstructions($filesize_warning)
->setValue($object->getFilesizeLimit()),
id(new PhabricatorTextEditField())
->setKey('copyTimeLimit')
->setLabel(pht('Clone/Fetch Timeout'))
->setTransactionType(
PhabricatorRepositoryCopyTimeLimitTransaction::TRANSACTIONTYPE)
->setDescription(
pht('Maximum permitted duration of internal clone/fetch.'))
->setConduitDescription(pht('Change the copy time limit.'))
->setConduitTypeDescription(pht('New repository copy time limit.'))
->setValue($object->getCopyTimeLimit()),
id(new PhabricatorTextEditField())
->setKey('touchLimit')
->setLabel(pht('Touched Paths Limit'))
->setTransactionType(
PhabricatorRepositoryTouchLimitTransaction::TRANSACTIONTYPE)
->setDescription(pht('Maximum permitted paths touched per commit.'))
->setConduitDescription(pht('Change the touch limit.'))
->setConduitTypeDescription(pht('New repository touch limit.'))
->setValue($object->getTouchLimit()),
);
}
}
diff --git a/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
index 8e964e3e71..54bf9daea7 100644
--- a/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
+++ b/src/applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php
@@ -1,26 +1,26 @@
<?php
final class DiffusionRepositoryIdentityEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorObjectsDescription() {
return pht('Repository Identity');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this identity.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getEditorApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/diffusion/editor/DiffusionURIEditEngine.php b/src/applications/diffusion/editor/DiffusionURIEditEngine.php
index dbc1238153..2c7f79359e 100644
--- a/src/applications/diffusion/editor/DiffusionURIEditEngine.php
+++ b/src/applications/diffusion/editor/DiffusionURIEditEngine.php
@@ -1,219 +1,219 @@
<?php
final class DiffusionURIEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'diffusion.uri';
private $repository;
public function setRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
public function getRepository() {
return $this->repository;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Repository URIs');
}
public function getSummaryHeader() {
return pht('Edit Repository URI');
}
public function getSummaryText() {
return pht('Creates and edits repository URIs.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function newEditableObject() {
$uri = PhabricatorRepositoryURI::initializeNewURI();
$repository = $this->getRepository();
if ($repository) {
$uri->setRepositoryPHID($repository->getPHID());
$uri->attachRepository($repository);
}
return $uri;
}
protected function newObjectQuery() {
return new PhabricatorRepositoryURIQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Repository URI');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Repository URI');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Repository URI %d', $object->getID());
}
protected function getObjectEditShortText($object) {
return pht('URI %d', $object->getID());
}
protected function getObjectCreateShortText() {
return pht('Create Repository URI');
}
protected function getObjectName() {
return pht('Repository URI');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$uri_instructions = null;
if ($object->isBuiltin()) {
$is_builtin = true;
$uri_value = (string)$object->getDisplayURI();
switch ($object->getBuiltinProtocol()) {
case PhabricatorRepositoryURI::BUILTIN_PROTOCOL_SSH:
$uri_instructions = pht(
" - Configure [[ %s | %s ]] to change the SSH username.\n".
" - Configure [[ %s | %s ]] to change the SSH host.\n".
" - Configure [[ %s | %s ]] to change the SSH port.",
'/config/edit/diffusion.ssh-user/',
'diffusion.ssh-user',
'/config/edit/diffusion.ssh-host/',
'diffusion.ssh-host',
'/config/edit/diffusion.ssh-port/',
'diffusion.ssh-port');
break;
}
} else {
$is_builtin = false;
$uri_value = $object->getURI();
if ($object->getRepositoryPHID()) {
$repository = $object->getRepository();
if ($repository->isGit()) {
$uri_instructions = pht(
"Provide the URI of a Git repository. It should usually look ".
"like one of these examples:\n".
"\n".
"| Example Git URIs\n".
"| -----------------------\n".
"| `git@github.com:example/example.git`\n".
"| `ssh://user@host.com/git/example.git`\n".
"| `https://example.com/repository.git`");
} else if ($repository->isHg()) {
$uri_instructions = pht(
"Provide the URI of a Mercurial repository. It should usually ".
"look like one of these examples:\n".
"\n".
"| Example Mercurial URIs\n".
"|-----------------------\n".
"| `ssh://hg@bitbucket.org/example/repository`\n".
"| `https://bitbucket.org/example/repository`");
} else if ($repository->isSVN()) {
$uri_instructions = pht(
"Provide the **Repository Root** of a Subversion repository. ".
"You can identify this by running `svn info` in a working ".
"copy. It should usually look like one of these examples:\n".
"\n".
"| Example Subversion URIs\n".
"|-----------------------\n".
"| `http://svn.example.org/svnroot/`\n".
"| `svn+ssh://svn.example.com/svnroot/`\n".
"| `svn://svn.example.net/svnroot/`\n\n".
"You **MUST** specify the root of the repository, not a ".
"subdirectory.");
}
}
}
return array(
id(new PhabricatorHandlesEditField())
->setKey('repository')
->setAliases(array('repositoryPHID'))
->setLabel(pht('Repository'))
->setIsRequired(true)
->setIsFormField(false)
->setTransactionType(
PhabricatorRepositoryURITransaction::TYPE_REPOSITORY)
->setDescription(pht('The repository this URI is associated with.'))
->setConduitDescription(
pht(
'Create a URI in a given repository. This transaction type '.
'must be present when creating a new URI and must not be '.
'present when editing an existing URI.'))
->setConduitTypeDescription(
pht('Repository PHID to create a new URI for.'))
->setSingleValue($object->getRepositoryPHID()),
id(new PhabricatorTextEditField())
->setKey('uri')
->setLabel(pht('URI'))
->setTransactionType(PhabricatorRepositoryURITransaction::TYPE_URI)
->setDescription(pht('The repository URI.'))
->setConduitDescription(pht('Change the repository URI.'))
->setConduitTypeDescription(pht('New repository URI.'))
->setIsRequired(!$is_builtin)
->setIsLocked($is_builtin)
->setValue($uri_value)
->setControlInstructions($uri_instructions),
id(new PhabricatorSelectEditField())
->setKey('io')
->setLabel(pht('I/O Type'))
->setTransactionType(PhabricatorRepositoryURITransaction::TYPE_IO)
->setDescription(pht('URI I/O behavior.'))
->setConduitDescription(pht('Adjust I/O behavior.'))
->setConduitTypeDescription(pht('New I/O behavior.'))
->setValue($object->getIOType())
->setOptions($object->getAvailableIOTypeOptions()),
id(new PhabricatorSelectEditField())
->setKey('display')
->setLabel(pht('Display Type'))
->setTransactionType(PhabricatorRepositoryURITransaction::TYPE_DISPLAY)
->setDescription(pht('URI display behavior.'))
->setConduitDescription(pht('Change display behavior.'))
->setConduitTypeDescription(pht('New display behavior.'))
->setValue($object->getDisplayType())
->setOptions($object->getAvailableDisplayTypeOptions()),
id(new PhabricatorHandlesEditField())
->setKey('credential')
->setAliases(array('credentialPHID'))
->setLabel(pht('Credential'))
->setIsFormField(false)
->setTransactionType(
PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL)
->setDescription(
pht('The credential to use when interacting with this URI.'))
->setConduitDescription(pht('Change the credential for this URI.'))
->setConduitTypeDescription(pht('New credential PHID, or null.'))
->setSingleValue($object->getCredentialPHID()),
id(new PhabricatorBoolEditField())
->setKey('disable')
->setLabel(pht('Disabled'))
->setIsFormField(false)
->setTransactionType(PhabricatorRepositoryURITransaction::TYPE_DISABLE)
->setDescription(pht('Active status of the URI.'))
->setConduitDescription(pht('Disable or activate the URI.'))
->setConduitTypeDescription(pht('True to disable the URI.'))
->setOptions(pht('Enable'), pht('Disable'))
->setValue($object->getIsDisabled()),
);
}
}
diff --git a/src/applications/diffusion/editor/DiffusionURIEditor.php b/src/applications/diffusion/editor/DiffusionURIEditor.php
index 90ced865f0..b8aecca8a3 100644
--- a/src/applications/diffusion/editor/DiffusionURIEditor.php
+++ b/src/applications/diffusion/editor/DiffusionURIEditor.php
@@ -1,517 +1,517 @@
<?php
final class DiffusionURIEditor
extends PhabricatorApplicationTransactionEditor {
private $repository;
private $repositoryPHID;
public function getEditorApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Diffusion URIs');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorRepositoryURITransaction::TYPE_REPOSITORY;
$types[] = PhabricatorRepositoryURITransaction::TYPE_URI;
$types[] = PhabricatorRepositoryURITransaction::TYPE_IO;
$types[] = PhabricatorRepositoryURITransaction::TYPE_DISPLAY;
$types[] = PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL;
$types[] = PhabricatorRepositoryURITransaction::TYPE_DISABLE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryURITransaction::TYPE_URI:
return $object->getURI();
case PhabricatorRepositoryURITransaction::TYPE_IO:
return $object->getIOType();
case PhabricatorRepositoryURITransaction::TYPE_DISPLAY:
return $object->getDisplayType();
case PhabricatorRepositoryURITransaction::TYPE_REPOSITORY:
return $object->getRepositoryPHID();
case PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL:
return $object->getCredentialPHID();
case PhabricatorRepositoryURITransaction::TYPE_DISABLE:
return (int)$object->getIsDisabled();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryURITransaction::TYPE_URI:
case PhabricatorRepositoryURITransaction::TYPE_IO:
case PhabricatorRepositoryURITransaction::TYPE_DISPLAY:
case PhabricatorRepositoryURITransaction::TYPE_REPOSITORY:
case PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL:
return $xaction->getNewValue();
case PhabricatorRepositoryURITransaction::TYPE_DISABLE:
return (int)$xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryURITransaction::TYPE_URI:
if (!$this->getIsNewObject()) {
$old_uri = $object->getEffectiveURI();
} else {
$old_uri = null;
// When creating a URI via the API, we may not have processed the
// repository transaction yet. Attach the repository here to make
// sure we have it for the calls below.
if ($this->repository) {
$object->attachRepository($this->repository);
}
}
$object->setURI($xaction->getNewValue());
// If we've changed the domain or protocol of the URI, remove the
// current credential. This improves behavior in several cases:
// If a user switches between protocols with different credential
// types, like HTTP and SSH, the old credential won't be valid anyway.
// It's cleaner to remove it than leave a bad credential in place.
// If a user switches hosts, the old credential is probably not
// correct (and potentially confusing/misleading). Removing it forces
// users to double check that they have the correct credentials.
// If an attacker can't see a symmetric credential like a username and
// password, they could still potentially capture it by changing the
// host for a URI that uses it to `evil.com`, a server they control,
// then observing the requests. Removing the credential prevents this
// kind of escalation.
// Since port and path changes are less likely to fall among these
// cases, they don't trigger a credential wipe.
$new_uri = $object->getEffectiveURI();
if ($old_uri) {
$new_proto = ($old_uri->getProtocol() != $new_uri->getProtocol());
$new_domain = ($old_uri->getDomain() != $new_uri->getDomain());
if ($new_proto || $new_domain) {
$object->setCredentialPHID(null);
}
}
break;
case PhabricatorRepositoryURITransaction::TYPE_IO:
$object->setIOType($xaction->getNewValue());
break;
case PhabricatorRepositoryURITransaction::TYPE_DISPLAY:
$object->setDisplayType($xaction->getNewValue());
break;
case PhabricatorRepositoryURITransaction::TYPE_REPOSITORY:
$object->setRepositoryPHID($xaction->getNewValue());
$object->attachRepository($this->repository);
break;
case PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL:
$object->setCredentialPHID($xaction->getNewValue());
break;
case PhabricatorRepositoryURITransaction::TYPE_DISABLE:
$object->setIsDisabled($xaction->getNewValue());
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryURITransaction::TYPE_URI:
case PhabricatorRepositoryURITransaction::TYPE_IO:
case PhabricatorRepositoryURITransaction::TYPE_DISPLAY:
case PhabricatorRepositoryURITransaction::TYPE_REPOSITORY:
case PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL:
case PhabricatorRepositoryURITransaction::TYPE_DISABLE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorRepositoryURITransaction::TYPE_REPOSITORY:
// Save this, since we need it to validate TYPE_IO transactions.
$this->repositoryPHID = $object->getRepositoryPHID();
$missing = $this->validateIsEmptyTextField(
$object->getRepositoryPHID(),
$xactions);
if ($missing) {
// NOTE: This isn't being marked as a missing field error because
// it's a fundamental, required property of the URI.
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht(
'When creating a repository URI, you must specify which '.
'repository the URI will belong to.'),
nonempty(last($xactions), null));
break;
}
$viewer = $this->getActor();
foreach ($xactions as $xaction) {
$repository_phid = $xaction->getNewValue();
// If this isn't changing anything, let it through as-is.
if ($repository_phid == $object->getRepositoryPHID()) {
continue;
}
if (!$this->getIsNewObject()) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'The repository a URI is associated with is immutable, and '.
'can not be changed after the URI is created.'),
$xaction);
continue;
}
$repository = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->withPHIDs(array($repository_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$repository) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'To create a URI for a repository ("%s"), it must exist and '.
'you must have permission to edit it.',
$repository_phid),
$xaction);
continue;
}
$this->repository = $repository;
$this->repositoryPHID = $repository_phid;
}
break;
case PhabricatorRepositoryURITransaction::TYPE_CREDENTIAL:
$viewer = $this->getActor();
foreach ($xactions as $xaction) {
$credential_phid = $xaction->getNewValue();
if ($credential_phid == $object->getCredentialPHID()) {
continue;
}
// Anyone who can edit a URI can remove the credential.
if ($credential_phid === null) {
continue;
}
$credential = id(new PassphraseCredentialQuery())
->setViewer($viewer)
->withPHIDs(array($credential_phid))
->executeOne();
if (!$credential) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'You can only associate a credential ("%s") with a repository '.
'URI if it exists and you have permission to see it.',
$credential_phid),
$xaction);
continue;
}
}
break;
case PhabricatorRepositoryURITransaction::TYPE_URI:
$missing = $this->validateIsEmptyTextField(
$object->getURI(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('A repository URI must have a nonempty URI.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
break;
}
foreach ($xactions as $xaction) {
$new_uri = $xaction->getNewValue();
if ($new_uri == $object->getURI()) {
continue;
}
try {
PhabricatorRepository::assertValidRemoteURI($new_uri);
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
continue;
}
}
break;
case PhabricatorRepositoryURITransaction::TYPE_IO:
$available = $object->getAvailableIOTypeOptions();
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (empty($available[$new])) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Value "%s" is not a valid IO setting for this URI. '.
'Available types for this URI are: %s.',
$new,
implode(', ', array_keys($available))),
$xaction);
continue;
}
// If we are setting this URI to use "Observe", we must have no
// other "Observe" URIs and must also have no "Read/Write" URIs.
// If we are setting this URI to "Read/Write", we must have no
// other "Observe" URIs. It's OK to have other "Read/Write" URIs.
$no_observers = false;
$no_readwrite = false;
switch ($new) {
case PhabricatorRepositoryURI::IO_OBSERVE:
$no_readwrite = true;
$no_observers = true;
break;
case PhabricatorRepositoryURI::IO_READWRITE:
$no_observers = true;
break;
}
if ($no_observers || $no_readwrite) {
$repository = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($this->repositoryPHID))
->needURIs(true)
->executeOne();
$uris = $repository->getURIs();
$observe_conflict = null;
$readwrite_conflict = null;
foreach ($uris as $uri) {
// If this is the URI being edited, it can not conflict with
// itself.
if ($uri->getID() == $object->getID()) {
continue;
}
$io_type = $uri->getEffectiveIOType();
if ($io_type == PhabricatorRepositoryURI::IO_READWRITE) {
if ($no_readwrite) {
$readwrite_conflict = $uri;
break;
}
}
if ($io_type == PhabricatorRepositoryURI::IO_OBSERVE) {
if ($no_observers) {
$observe_conflict = $uri;
break;
}
}
}
if ($observe_conflict) {
if ($new == PhabricatorRepositoryURI::IO_OBSERVE) {
$message = pht(
'You can not set this URI to use Observe IO because '.
'another URI for this repository is already configured '.
'in Observe IO mode. A repository can not observe two '.
'different remotes simultaneously. Turn off IO for the '.
'other URI first.');
} else {
$message = pht(
'You can not set this URI to use Read/Write IO because '.
'another URI for this repository is already configured '.
'in Observe IO mode. An observed repository can not be '.
'made writable. Turn off IO for the other URI first.');
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
continue;
}
if ($readwrite_conflict) {
$message = pht(
'You can not set this URI to use Observe IO because '.
'another URI for this repository is already configured '.
'in Read/Write IO mode. A repository can not simultaneously '.
'be writable and observe a remote. Turn off IO for the '.
'other URI first.');
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
continue;
}
}
}
break;
case PhabricatorRepositoryURITransaction::TYPE_DISPLAY:
$available = $object->getAvailableDisplayTypeOptions();
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (empty($available[$new])) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Value "%s" is not a valid display setting for this URI. '.
'Available types for this URI are: %s.',
$new,
implode(', ', array_keys($available))));
}
}
break;
case PhabricatorRepositoryURITransaction::TYPE_DISABLE:
$old = $object->getIsDisabled();
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if ($old == $new) {
continue;
}
if (!$object->isBuiltin()) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('You can not manually disable builtin URIs.'));
}
break;
}
return $errors;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// Synchronize the repository state based on the presence of an "Observe"
// URI.
$repository = $object->getRepository();
$uris = id(new PhabricatorRepositoryURIQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withRepositories(array($repository))
->execute();
// Reattach the current URIs to the repository: we're going to rebuild
// the index explicitly below, and want to include any changes made to
// this URI in the index update.
$repository->attachURIs($uris);
$observe_uri = null;
foreach ($uris as $uri) {
if ($uri->getIoType() != PhabricatorRepositoryURI::IO_OBSERVE) {
continue;
}
$observe_uri = $uri;
break;
}
$was_hosted = $repository->isHosted();
if ($observe_uri) {
$repository
->setHosted(false)
->setDetail('remote-uri', (string)$observe_uri->getEffectiveURI())
->setCredentialPHID($observe_uri->getCredentialPHID());
} else {
$repository
->setHosted(true)
->setDetail('remote-uri', null)
->setCredentialPHID(null);
}
$repository->save();
// Explicitly update the URI index.
$repository->updateURIIndex();
$is_hosted = $repository->isHosted();
// If we've swapped the repository from hosted to observed or vice versa,
// reset all the cluster version clocks.
if ($was_hosted != $is_hosted) {
$cluster_engine = id(new DiffusionRepositoryClusterEngine())
->setViewer($this->getActor())
->setRepository($repository)
->synchronizeWorkingCopyAfterHostingChange();
}
$repository->writeStatusMessage(
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
null);
return $xactions;
}
}
diff --git a/src/applications/diffusion/herald/HeraldCommitAdapter.php b/src/applications/diffusion/herald/HeraldCommitAdapter.php
index af7c757cd9..0ec9de7e87 100644
--- a/src/applications/diffusion/herald/HeraldCommitAdapter.php
+++ b/src/applications/diffusion/herald/HeraldCommitAdapter.php
@@ -1,405 +1,405 @@
<?php
final class HeraldCommitAdapter
extends HeraldAdapter
implements HarbormasterBuildableAdapterInterface {
protected $diff;
protected $revision;
protected $commit;
private $commitDiff;
protected $affectedPaths;
protected $affectedRevision;
protected $affectedPackages;
protected $auditNeededPackages;
private $buildRequests = array();
public function getAdapterApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function newObject() {
return new PhabricatorRepositoryCommit();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PhabricatorRepositoryCommit);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run after a commit is discovered and imported.');
}
public function newTestAdapter(PhabricatorUser $viewer, $object) {
return id(clone $this)
->setObject($object);
}
protected function initializeNewAdapter() {
$this->commit = $this->newObject();
}
public function setObject($object) {
$viewer = $this->getViewer();
$commit_phid = $object->getPHID();
$commit = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withPHIDs(array($commit_phid))
->needCommitData(true)
->needIdentities(true)
->needAuditRequests(true)
->executeOne();
if (!$commit) {
throw new Exception(
pht(
'Failed to reload commit ("%s") to fetch commit data.',
$commit_phid));
}
$this->commit = $commit;
return $this;
}
public function getObject() {
return $this->commit;
}
public function getAdapterContentType() {
return 'commit';
}
public function getAdapterContentName() {
return pht('Commits');
}
public function getAdapterContentDescription() {
return pht(
"React to new commits appearing in tracked repositories.\n".
"Commit rules can send email, flag commits, trigger audits, ".
"and run build plans.");
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
return true;
default:
return false;
}
}
public function canTriggerOnObject($object) {
if ($object instanceof PhabricatorRepository) {
return true;
}
if ($object instanceof PhabricatorProject) {
return true;
}
return false;
}
public function getTriggerObjectPHIDs() {
$project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$repository_phid = $this->getRepository()->getPHID();
$commit_phid = $this->getObject()->getPHID();
$phids = array();
$phids[] = $commit_phid;
$phids[] = $repository_phid;
// NOTE: This is projects for the repository, not for the commit. When
// Herald evaluates, commits normally can not have any project tags yet.
$repository_project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$repository_phid,
$project_type);
foreach ($repository_project_phids as $phid) {
$phids[] = $phid;
}
$phids = array_unique($phids);
$phids = array_values($phids);
return $phids;
}
public function explainValidTriggerObjects() {
return pht('This rule can trigger for **repositories** and **projects**.');
}
public function getHeraldName() {
return $this->commit->getMonogram();
}
public function loadAffectedPaths() {
$viewer = $this->getViewer();
if ($this->affectedPaths === null) {
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
$this->getRepository(),
$this->commit,
$viewer);
$this->affectedPaths = $result;
}
return $this->affectedPaths;
}
public function loadAffectedPackages() {
if ($this->affectedPackages === null) {
$packages = PhabricatorOwnersPackage::loadAffectedPackages(
$this->getRepository(),
$this->loadAffectedPaths());
$this->affectedPackages = $packages;
}
return $this->affectedPackages;
}
public function loadAuditNeededPackages() {
if ($this->auditNeededPackages === null) {
$status_arr = array(
PhabricatorAuditRequestStatus::AUDIT_REQUIRED,
PhabricatorAuditRequestStatus::CONCERNED,
);
$requests = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere(
'commitPHID = %s AND auditStatus IN (%Ls)',
$this->commit->getPHID(),
$status_arr);
$this->auditNeededPackages = $requests;
}
return $this->auditNeededPackages;
}
public function loadDifferentialRevision() {
if ($this->affectedRevision === null) {
$viewer = $this->getViewer();
// NOTE: The viewer here is omnipotent, which means that Herald discloses
// some information users do not normally have access to when rules load
// the revision related to a commit. See D20468.
// A user who wants to learn about "Dxyz" can write a Herald rule which
// uses all the "Related revision..." fields, then push a commit which
// contains "Differential Revision: Dxyz" in the message to make Herald
// evaluate the commit with "Dxyz" as the related revision.
// At time of writing, this commit will link to the revision and the
// transcript for the commit will disclose some information about the
// revision (like reviewers, subscribers, and build status) which the
// commit author could not otherwise see.
// For now, we just accept this. The disclosures are relatively
// uninteresting and you have to jump through a lot of hoops (and leave
// a lot of evidence) to get this information.
$revision = DiffusionCommitRevisionQuery::loadRevisionForCommit(
$viewer,
$this->getObject());
if ($revision) {
$this->affectedRevision = $revision;
} else {
$this->affectedRevision = false;
}
}
return $this->affectedRevision;
}
public static function getEnormousByteLimit() {
return 256 * 1024 * 1024; // 256MB. See T13142 and T13143.
}
public static function getEnormousTimeLimit() {
return 60 * 15; // 15 Minutes
}
private function loadCommitDiff() {
$viewer = $this->getViewer();
$byte_limit = self::getEnormousByteLimit();
$time_limit = self::getEnormousTimeLimit();
$diff_info = $this->callConduit(
'diffusion.rawdiffquery',
array(
'commit' => $this->commit->getCommitIdentifier(),
'timeout' => $time_limit,
'byteLimit' => $byte_limit,
'linesOfContext' => 0,
));
if ($diff_info['tooHuge']) {
throw new Exception(
pht(
'The raw text of this change is enormous (larger than %s byte(s)). '.
'Herald can not process it.',
new PhutilNumber($byte_limit)));
}
if ($diff_info['tooSlow']) {
throw new Exception(
pht(
'The raw text of this change took too long to process (longer '.
'than %s second(s)). Herald can not process it.',
new PhutilNumber($time_limit)));
}
$file_phid = $diff_info['filePHID'];
$diff_file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
if (!$diff_file) {
throw new Exception(
pht(
'Failed to load diff ("%s") for this change.',
$file_phid));
}
$raw = $diff_file->loadFileData();
// See T13667. This happens when a commit is empty and affects no files.
if (!strlen($raw)) {
return false;
}
$parser = new ArcanistDiffParser();
$changes = $parser->parseDiff($raw);
$diff = DifferentialDiff::newEphemeralFromRawChanges(
$changes);
return $diff;
}
public function isDiffEnormous() {
$this->loadDiffContent('*');
return ($this->commitDiff instanceof Exception);
}
public function loadDiffContent($type) {
if ($this->commitDiff === null) {
try {
$this->commitDiff = $this->loadCommitDiff();
} catch (Exception $ex) {
$this->commitDiff = $ex;
phlog($ex);
}
}
if ($this->commitDiff === false) {
return array();
}
if ($this->commitDiff instanceof Exception) {
$ex = $this->commitDiff;
$ex_class = get_class($ex);
$ex_message = pht('Failed to load changes: %s', $ex->getMessage());
return array(
'<'.$ex_class.'>' => $ex_message,
);
}
$changes = $this->commitDiff->getChangesets();
$result = array();
foreach ($changes as $change) {
$lines = array();
foreach ($change->getHunks() as $hunk) {
switch ($type) {
case '-':
$lines[] = $hunk->makeOldFile();
break;
case '+':
$lines[] = $hunk->makeNewFile();
break;
case '*':
$lines[] = $hunk->makeChanges();
break;
default:
throw new Exception(pht("Unknown content selection '%s'!", $type));
}
}
$result[$change->getFilename()] = implode("\n", $lines);
}
return $result;
}
public function loadIsMergeCommit() {
$parents = $this->callConduit(
'diffusion.commitparentsquery',
array(
'commit' => $this->getObject()->getCommitIdentifier(),
));
return (count($parents) > 1);
}
private function callConduit($method, array $params) {
$viewer = $this->getViewer();
$drequest = DiffusionRequest::newFromDictionary(
array(
'user' => $viewer,
'repository' => $this->getRepository(),
'commit' => $this->commit->getCommitIdentifier(),
));
return DiffusionQuery::callConduitWithDiffusionRequest(
$viewer,
$drequest,
$method,
$params);
}
private function getRepository() {
return $this->getObject()->getRepository();
}
public function getAuthorPHID() {
return $this->getObject()->getEffectiveAuthorPHID();
}
public function getCommitterPHID() {
$commit = $this->getObject();
if ($commit->hasCommitterIdentity()) {
$identity = $commit->getCommitterIdentity();
return $identity->getCurrentEffectiveUserPHID();
}
return null;
}
/* -( HarbormasterBuildableAdapterInterface )------------------------------ */
public function getHarbormasterBuildablePHID() {
return $this->getObject()->getPHID();
}
public function getHarbormasterContainerPHID() {
return $this->getObject()->getRepository()->getPHID();
}
public function getQueuedHarbormasterBuildRequests() {
return $this->buildRequests;
}
public function queueHarbormasterBuildRequest(
HarbormasterBuildRequest $request) {
$this->buildRequests[] = $request;
}
}
diff --git a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
index f63f647da6..4707545e9d 100644
--- a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
+++ b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
@@ -1,94 +1,94 @@
<?php
abstract class HeraldPreCommitAdapter extends HeraldAdapter {
private $log;
private $hookEngine;
abstract public function isPreCommitRefAdapter();
public function setPushLog(PhabricatorRepositoryPushLog $log) {
$this->log = $log;
return $this;
}
public function setHookEngine(DiffusionCommitHookEngine $engine) {
$this->hookEngine = $engine;
return $this;
}
public function getHookEngine() {
return $this->hookEngine;
}
public function getAdapterApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function isTestAdapterForObject($object) {
return ($object instanceof PhabricatorRepositoryCommit);
}
public function canCreateTestAdapterForObject($object) {
return false;
}
public function getAdapterTestDescription() {
return pht(
'Commit hook events depend on repository state which is only available '.
'at push time, and can not be run in test mode.');
}
protected function initializeNewAdapter() {
$this->log = new PhabricatorRepositoryPushLog();
}
public function isSingleEventAdapter() {
return true;
}
public function getObject() {
return $this->log;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
default:
return false;
}
}
public function canTriggerOnObject($object) {
if ($object instanceof PhabricatorRepository) {
return true;
}
if ($object instanceof PhabricatorProject) {
return true;
}
return false;
}
public function explainValidTriggerObjects() {
return pht('This rule can trigger for **repositories** or **projects**.');
}
public function getTriggerObjectPHIDs() {
return array_merge(
array(
$this->hookEngine->getRepository()->getPHID(),
$this->getPHID(),
),
$this->hookEngine->getRepository()->getProjectPHIDs());
}
public function supportsWebhooks() {
return false;
}
}
diff --git a/src/applications/diffusion/query/DiffusionCommitHintQuery.php b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
index c0794a4387..fdf30e693b 100644
--- a/src/applications/diffusion/query/DiffusionCommitHintQuery.php
+++ b/src/applications/diffusion/query/DiffusionCommitHintQuery.php
@@ -1,112 +1,112 @@
<?php
final class DiffusionCommitHintQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $repositoryPHIDs;
private $oldCommitIdentifiers;
private $commits;
private $commitMap;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withOldCommitIdentifiers(array $identifiers) {
$this->oldCommitIdentifiers = $identifiers;
return $this;
}
public function withCommits(array $commits) {
assert_instances_of($commits, 'PhabricatorRepositoryCommit');
$repository_phids = array();
foreach ($commits as $commit) {
$repository_phids[] = $commit->getRepository()->getPHID();
}
$this->repositoryPHIDs = $repository_phids;
$this->oldCommitIdentifiers = mpull($commits, 'getCommitIdentifier');
$this->commits = $commits;
return $this;
}
public function getCommitMap() {
if ($this->commitMap === null) {
throw new PhutilInvalidStateException('execute');
}
return $this->commitMap;
}
public function newResultObject() {
return new PhabricatorRepositoryCommitHint();
}
protected function willExecute() {
$this->commitMap = array();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->oldCommitIdentifiers !== null) {
$where[] = qsprintf(
$conn,
'oldCommitIdentifier IN (%Ls)',
$this->oldCommitIdentifiers);
}
return $where;
}
protected function didFilterPage(array $hints) {
if ($this->commits) {
$map = array();
foreach ($this->commits as $commit) {
$repository_phid = $commit->getRepository()->getPHID();
$identifier = $commit->getCommitIdentifier();
$map[$repository_phid][$identifier] = $commit->getPHID();
}
foreach ($hints as $hint) {
$repository_phid = $hint->getRepositoryPHID();
$identifier = $hint->getOldCommitIdentifier();
if (isset($map[$repository_phid][$identifier])) {
$commit_phid = $map[$repository_phid][$identifier];
$this->commitMap[$commit_phid] = $hint;
}
}
}
return $hints;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php
index 7b4e80bfec..e1bec46441 100644
--- a/src/applications/diffusion/query/DiffusionCommitQuery.php
+++ b/src/applications/diffusion/query/DiffusionCommitQuery.php
@@ -1,995 +1,995 @@
<?php
final class DiffusionCommitQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $defaultRepository;
private $identifiers;
private $repositoryIDs;
private $repositoryPHIDs;
private $identifierMap;
private $responsiblePHIDs;
private $statuses;
private $packagePHIDs;
private $unreachable;
private $permanent;
private $needAuditRequests;
private $needAuditAuthority;
private $auditIDs;
private $auditorPHIDs;
private $epochMin;
private $epochMax;
private $importing;
private $ancestorsOf;
private $needCommitData;
private $needDrafts;
private $needIdentities;
private $mustFilterRefs = false;
private $refRepository;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
/**
* Load commits by partial or full identifiers, e.g. "rXab82393", "rX1234",
* or "a9caf12". When an identifier matches multiple commits, they will all
* be returned; callers should be prepared to deal with more results than
* they queried for.
*/
public function withIdentifiers(array $identifiers) {
// Some workflows (like blame lookups) can pass in large numbers of
// duplicate identifiers. We only care about unique identifiers, so
// get rid of duplicates immediately.
$identifiers = array_fuse($identifiers);
$this->identifiers = $identifiers;
return $this;
}
/**
* Look up commits in a specific repository. This is a shorthand for calling
* @{method:withDefaultRepository} and @{method:withRepositoryIDs}.
*/
public function withRepository(PhabricatorRepository $repository) {
$this->withDefaultRepository($repository);
$this->withRepositoryIDs(array($repository->getID()));
return $this;
}
/**
* Look up commits in a specific repository. Prefer
* @{method:withRepositoryIDs}; the underlying table is keyed by ID such
* that this method requires a separate initial query to map PHID to ID.
*/
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
/**
* If a default repository is provided, ambiguous commit identifiers will
* be assumed to belong to the default repository.
*
* For example, "r123" appearing in a commit message in repository X is
* likely to be unambiguously "rX123". Normally the reference would be
* considered ambiguous, but if you provide a default repository it will
* be correctly resolved.
*/
public function withDefaultRepository(PhabricatorRepository $repository) {
$this->defaultRepository = $repository;
return $this;
}
public function withRepositoryIDs(array $repository_ids) {
$this->repositoryIDs = array_unique($repository_ids);
return $this;
}
public function needCommitData($need) {
$this->needCommitData = $need;
return $this;
}
public function needDrafts($need) {
$this->needDrafts = $need;
return $this;
}
public function needIdentities($need) {
$this->needIdentities = $need;
return $this;
}
public function needAuditRequests($need) {
$this->needAuditRequests = $need;
return $this;
}
public function needAuditAuthority(array $users) {
assert_instances_of($users, 'PhabricatorUser');
$this->needAuditAuthority = $users;
return $this;
}
public function withAuditIDs(array $ids) {
$this->auditIDs = $ids;
return $this;
}
public function withAuditorPHIDs(array $auditor_phids) {
$this->auditorPHIDs = $auditor_phids;
return $this;
}
public function withResponsiblePHIDs(array $responsible_phids) {
$this->responsiblePHIDs = $responsible_phids;
return $this;
}
public function withPackagePHIDs(array $package_phids) {
$this->packagePHIDs = $package_phids;
return $this;
}
public function withUnreachable($unreachable) {
$this->unreachable = $unreachable;
return $this;
}
public function withPermanent($permanent) {
$this->permanent = $permanent;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withEpochRange($min, $max) {
$this->epochMin = $min;
$this->epochMax = $max;
return $this;
}
public function withImporting($importing) {
$this->importing = $importing;
return $this;
}
public function withAncestorsOf(array $refs) {
$this->ancestorsOf = $refs;
return $this;
}
public function getIdentifierMap() {
if ($this->identifierMap === null) {
throw new Exception(
pht(
'You must %s the query before accessing the identifier map.',
'execute()'));
}
return $this->identifierMap;
}
protected function getPrimaryTableAlias() {
return 'commit';
}
protected function willExecute() {
if ($this->identifierMap === null) {
$this->identifierMap = array();
}
}
public function newResultObject() {
return new PhabricatorRepositoryCommit();
}
protected function loadPage() {
$table = $this->newResultObject();
$conn = $table->establishConnection('r');
$empty_exception = null;
$subqueries = array();
if ($this->responsiblePHIDs) {
$base_authors = $this->authorPHIDs;
$base_auditors = $this->auditorPHIDs;
$responsible_phids = $this->responsiblePHIDs;
if ($base_authors) {
$all_authors = array_merge($base_authors, $responsible_phids);
} else {
$all_authors = $responsible_phids;
}
if ($base_auditors) {
$all_auditors = array_merge($base_auditors, $responsible_phids);
} else {
$all_auditors = $responsible_phids;
}
$this->authorPHIDs = $all_authors;
$this->auditorPHIDs = $base_auditors;
try {
$subqueries[] = $this->buildStandardPageQuery(
$conn,
$table->getTableName());
} catch (PhabricatorEmptyQueryException $ex) {
$empty_exception = $ex;
}
$this->authorPHIDs = $base_authors;
$this->auditorPHIDs = $all_auditors;
try {
$subqueries[] = $this->buildStandardPageQuery(
$conn,
$table->getTableName());
} catch (PhabricatorEmptyQueryException $ex) {
$empty_exception = $ex;
}
} else {
$subqueries[] = $this->buildStandardPageQuery(
$conn,
$table->getTableName());
}
if (!$subqueries) {
throw $empty_exception;
}
if (count($subqueries) > 1) {
$unions = null;
foreach ($subqueries as $subquery) {
if (!$unions) {
$unions = qsprintf(
$conn,
'(%Q)',
$subquery);
continue;
}
$unions = qsprintf(
$conn,
'%Q UNION DISTINCT (%Q)',
$unions,
$subquery);
}
$query = qsprintf(
$conn,
'%Q %Q %Q',
$unions,
$this->buildOrderClause($conn, true),
$this->buildLimitClause($conn));
} else {
$query = head($subqueries);
}
$rows = queryfx_all($conn, '%Q', $query);
$rows = $this->didLoadRawRows($rows);
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $commits) {
$repository_ids = mpull($commits, 'getRepositoryID', 'getRepositoryID');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIDs($repository_ids)
->execute();
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$result = array();
foreach ($commits as $key => $commit) {
$repo = idx($repos, $commit->getRepositoryID());
if ($repo) {
$commit->attachRepository($repo);
} else {
$this->didRejectResult($commit);
unset($commits[$key]);
continue;
}
// Build the identifierMap
if ($this->identifiers !== null) {
$ids = $this->identifiers;
$prefixes = array(
'r'.$commit->getRepository()->getCallsign(),
'r'.$commit->getRepository()->getCallsign().':',
'R'.$commit->getRepository()->getID().':',
'', // No prefix is valid too and will only match the commitIdentifier
);
$suffix = $commit->getCommitIdentifier();
if ($commit->getRepository()->isSVN()) {
foreach ($prefixes as $prefix) {
if (isset($ids[$prefix.$suffix])) {
$result[$prefix.$suffix][] = $commit;
}
}
} else {
// This awkward construction is so we can link the commits up in O(N)
// time instead of O(N^2).
for ($ii = $min_qualified; $ii <= strlen($suffix); $ii++) {
$part = substr($suffix, 0, $ii);
foreach ($prefixes as $prefix) {
if (isset($ids[$prefix.$part])) {
$result[$prefix.$part][] = $commit;
}
}
}
}
}
}
if ($result) {
foreach ($result as $identifier => $matching_commits) {
if (count($matching_commits) == 1) {
$result[$identifier] = head($matching_commits);
} else {
// This reference is ambiguous (it matches more than one commit) so
// don't link it.
unset($result[$identifier]);
}
}
$this->identifierMap += $result;
}
return $commits;
}
protected function didFilterPage(array $commits) {
$viewer = $this->getViewer();
if ($this->mustFilterRefs) {
// If this flag is set, the query has an "Ancestors Of" constraint and
// at least one of the constraining refs had too many ancestors for us
// to apply the constraint with a big "commitIdentifier IN (%Ls)" clause.
// We're going to filter each page and hope we get a full result set
// before the query overheats.
$ancestor_list = mpull($commits, 'getCommitIdentifier');
$ancestor_list = array_values($ancestor_list);
foreach ($this->ancestorsOf as $ref) {
try {
$ancestor_list = DiffusionQuery::callConduitWithDiffusionRequest(
$viewer,
DiffusionRequest::newFromDictionary(
array(
'repository' => $this->refRepository,
'user' => $viewer,
)),
'diffusion.internal.ancestors',
array(
'ref' => $ref,
'commits' => $ancestor_list,
));
} catch (ConduitClientException $ex) {
throw new PhabricatorSearchConstraintException(
$ex->getMessage());
}
if (!$ancestor_list) {
break;
}
}
$ancestor_list = array_fuse($ancestor_list);
foreach ($commits as $key => $commit) {
$identifier = $commit->getCommitIdentifier();
if (!isset($ancestor_list[$identifier])) {
$this->didRejectResult($commit);
unset($commits[$key]);
}
}
if (!$commits) {
return $commits;
}
}
if ($this->needCommitData) {
$data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID in (%Ld)',
mpull($commits, 'getID'));
$data = mpull($data, null, 'getCommitID');
foreach ($commits as $commit) {
$commit_data = idx($data, $commit->getID());
if (!$commit_data) {
$commit_data = new PhabricatorRepositoryCommitData();
}
$commit->attachCommitData($commit_data);
}
}
if ($this->needAuditRequests) {
$requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'commitPHID IN (%Ls)',
mpull($commits, 'getPHID'));
$requests = mgroup($requests, 'getCommitPHID');
foreach ($commits as $commit) {
$audit_requests = idx($requests, $commit->getPHID(), array());
$commit->attachAudits($audit_requests);
foreach ($audit_requests as $audit_request) {
$audit_request->attachCommit($commit);
}
}
}
if ($this->needIdentities) {
$identity_phids = array_merge(
mpull($commits, 'getAuthorIdentityPHID'),
mpull($commits, 'getCommitterIdentityPHID'));
$data = id(new PhabricatorRepositoryIdentityQuery())
->withPHIDs($identity_phids)
->setViewer($this->getViewer())
->execute();
$data = mpull($data, null, 'getPHID');
foreach ($commits as $commit) {
$author_identity = idx($data, $commit->getAuthorIdentityPHID());
$committer_identity = idx($data, $commit->getCommitterIdentityPHID());
$commit->attachIdentities($author_identity, $committer_identity);
}
}
if ($this->needDrafts) {
PhabricatorDraftEngine::attachDrafts(
$viewer,
$commits);
}
if ($this->needAuditAuthority) {
$authority_users = $this->needAuditAuthority;
// NOTE: This isn't very efficient since we're running two queries per
// user, but there's currently no way to figure out authority for
// multiple users in one query. Today, we only ever request authority for
// a single user and single commit, so this has no practical impact.
// NOTE: We're querying with the viewership of query viewer, not the
// actual users. If the viewer can't see a project or package, they
// won't be able to see who has authority on it. This is safer than
// showing them true authority, and should never matter today, but it
// also doesn't seem like a significant disclosure and might be
// reasonable to adjust later if it causes something weird or confusing
// to happen.
$authority_map = array();
foreach ($authority_users as $authority_user) {
$authority_phid = $authority_user->getPHID();
if (!$authority_phid) {
continue;
}
$result_phids = array();
// Users have authority over themselves.
$result_phids[] = $authority_phid;
// Users have authority over packages they own.
$owned_packages = id(new PhabricatorOwnersPackageQuery())
->setViewer($viewer)
->withAuthorityPHIDs(array($authority_phid))
->execute();
foreach ($owned_packages as $package) {
$result_phids[] = $package->getPHID();
}
// Users have authority over projects they're members of.
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs(array($authority_phid))
->execute();
foreach ($projects as $project) {
$result_phids[] = $project->getPHID();
}
$result_phids = array_fuse($result_phids);
foreach ($commits as $commit) {
$attach_phids = $result_phids;
// NOTE: When modifying your own commits, you act only on behalf of
// yourself, not your packages or projects. The idea here is that you
// can't accept your own commits. In the future, this might change or
// depend on configuration.
$author_phid = $commit->getAuthorPHID();
if ($author_phid == $authority_phid) {
$attach_phids = array($author_phid);
$attach_phids = array_fuse($attach_phids);
}
$commit->attachAuditAuthority($authority_user, $attach_phids);
}
}
}
return $commits;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->repositoryPHIDs !== null) {
$map_repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($this->repositoryPHIDs)
->execute();
if (!$map_repositories) {
throw new PhabricatorEmptyQueryException();
}
$repository_ids = mpull($map_repositories, 'getID');
if ($this->repositoryIDs !== null) {
$repository_ids = array_merge($repository_ids, $this->repositoryIDs);
}
$this->withRepositoryIDs($repository_ids);
}
if ($this->ancestorsOf !== null) {
if (count($this->repositoryIDs) !== 1) {
throw new PhabricatorSearchConstraintException(
pht(
'To search for commits which are ancestors of particular refs, '.
'you must constrain the search to exactly one repository.'));
}
$repository_id = head($this->repositoryIDs);
$history_limit = $this->getRawResultLimit() * 32;
$viewer = $this->getViewer();
$repository = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->withIDs(array($repository_id))
->executeOne();
if (!$repository) {
throw new PhabricatorEmptyQueryException();
}
if ($repository->isSVN()) {
throw new PhabricatorSearchConstraintException(
pht(
'Subversion does not support searching for ancestors of '.
'a particular ref. This operation is not meaningful in '.
'Subversion.'));
}
if ($repository->isHg()) {
throw new PhabricatorSearchConstraintException(
pht(
'Mercurial does not currently support searching for ancestors of '.
'a particular ref.'));
}
$can_constrain = true;
$history_identifiers = array();
foreach ($this->ancestorsOf as $key => $ref) {
try {
$raw_history = DiffusionQuery::callConduitWithDiffusionRequest(
$viewer,
DiffusionRequest::newFromDictionary(
array(
'repository' => $repository,
'user' => $viewer,
)),
'diffusion.historyquery',
array(
'commit' => $ref,
'limit' => $history_limit,
));
} catch (ConduitClientException $ex) {
throw new PhabricatorSearchConstraintException(
$ex->getMessage());
}
$ref_identifiers = array();
foreach ($raw_history['pathChanges'] as $change) {
$ref_identifiers[] = $change['commitIdentifier'];
}
// If this ref had fewer total commits than the limit, we're safe to
// apply the constraint as a large `IN (...)` query for a list of
// commit identifiers. This is efficient.
if ($history_limit) {
if (count($ref_identifiers) >= $history_limit) {
$can_constrain = false;
break;
}
}
$history_identifiers += array_fuse($ref_identifiers);
}
// If all refs had a small number of ancestors, we can just put the
// constraint into the query here and we're done. Otherwise, we need
// to filter each page after it comes out of the MySQL layer.
if ($can_constrain) {
$where[] = qsprintf(
$conn,
'commit.commitIdentifier IN (%Ls)',
$history_identifiers);
} else {
$this->mustFilterRefs = true;
$this->refRepository = $repository;
}
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'commit.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'commit.phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryIDs !== null) {
$where[] = qsprintf(
$conn,
'commit.repositoryID IN (%Ld)',
$this->repositoryIDs);
}
if ($this->authorPHIDs !== null) {
$author_phids = $this->authorPHIDs;
if ($author_phids) {
$author_phids = $this->selectPossibleAuthors($author_phids);
if (!$author_phids) {
throw new PhabricatorEmptyQueryException(
pht('Author PHIDs contain no possible authors.'));
}
}
$where[] = qsprintf(
$conn,
'commit.authorPHID IN (%Ls)',
$author_phids);
}
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'commit.epoch >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'commit.epoch <= %d',
$this->epochMax);
}
if ($this->importing !== null) {
if ($this->importing) {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) != %d',
PhabricatorRepositoryCommit::IMPORTED_ALL,
PhabricatorRepositoryCommit::IMPORTED_ALL);
} else {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) = %d',
PhabricatorRepositoryCommit::IMPORTED_ALL,
PhabricatorRepositoryCommit::IMPORTED_ALL);
}
}
if ($this->identifiers !== null) {
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$refs = array();
$bare = array();
foreach ($this->identifiers as $identifier) {
$matches = null;
preg_match('/^(?:[rR]([A-Z]+:?|[0-9]+:))?(.*)$/',
$identifier, $matches);
$repo = nonempty(rtrim($matches[1], ':'), null);
$commit_identifier = nonempty($matches[2], null);
if ($repo === null) {
if ($this->defaultRepository) {
$repo = $this->defaultRepository->getPHID();
}
}
if ($repo === null) {
if (strlen($commit_identifier) < $min_unqualified) {
continue;
}
$bare[] = $commit_identifier;
} else {
$refs[] = array(
'repository' => $repo,
'identifier' => $commit_identifier,
);
}
}
$sql = array();
foreach ($bare as $identifier) {
$sql[] = qsprintf(
$conn,
'(commit.commitIdentifier LIKE %> AND '.
'LENGTH(commit.commitIdentifier) = 40)',
$identifier);
}
if ($refs) {
$repositories = ipull($refs, 'repository');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIdentifiers($repositories);
$repos->execute();
$repos = $repos->getIdentifierMap();
foreach ($refs as $key => $ref) {
$repo = idx($repos, $ref['repository']);
if (!$repo) {
continue;
}
if ($repo->isSVN()) {
if (!ctype_digit((string)$ref['identifier'])) {
continue;
}
$sql[] = qsprintf(
$conn,
'(commit.repositoryID = %d AND commit.commitIdentifier = %s)',
$repo->getID(),
// NOTE: Because the 'commitIdentifier' column is a string, MySQL
// ignores the index if we hand it an integer. Hand it a string.
// See T3377.
(int)$ref['identifier']);
} else {
if (strlen($ref['identifier']) < $min_qualified) {
continue;
}
$identifier = $ref['identifier'];
if (strlen($identifier) == 40) {
// MySQL seems to do slightly better with this version if the
// clause, so issue it if we have a full commit hash.
$sql[] = qsprintf(
$conn,
'(commit.repositoryID = %d
AND commit.commitIdentifier = %s)',
$repo->getID(),
$identifier);
} else {
$sql[] = qsprintf(
$conn,
'(commit.repositoryID = %d
AND commit.commitIdentifier LIKE %>)',
$repo->getID(),
$identifier);
}
}
}
}
if (!$sql) {
// If we discarded all possible identifiers (e.g., they all referenced
// bogus repositories or were all too short), make sure the query finds
// nothing.
throw new PhabricatorEmptyQueryException(
pht('No commit identifiers.'));
}
$where[] = qsprintf($conn, '%LO', $sql);
}
if ($this->auditIDs !== null) {
$where[] = qsprintf(
$conn,
'auditor.id IN (%Ld)',
$this->auditIDs);
}
if ($this->auditorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'auditor.auditorPHID IN (%Ls)',
$this->auditorPHIDs);
}
if ($this->statuses !== null) {
$statuses = DiffusionCommitAuditStatus::newModernKeys(
$this->statuses);
$where[] = qsprintf(
$conn,
'commit.auditStatus IN (%Ls)',
$statuses);
}
if ($this->packagePHIDs !== null) {
$where[] = qsprintf(
$conn,
'package.dst IN (%Ls)',
$this->packagePHIDs);
}
if ($this->unreachable !== null) {
if ($this->unreachable) {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) = %d',
PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE,
PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE);
} else {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) = 0',
PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE);
}
}
if ($this->permanent !== null) {
if ($this->permanent) {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) = %d',
PhabricatorRepositoryCommit::IMPORTED_PERMANENT,
PhabricatorRepositoryCommit::IMPORTED_PERMANENT);
} else {
$where[] = qsprintf(
$conn,
'(commit.importStatus & %d) = 0',
PhabricatorRepositoryCommit::IMPORTED_PERMANENT);
}
}
return $where;
}
protected function didFilterResults(array $filtered) {
if ($this->identifierMap) {
foreach ($this->identifierMap as $name => $commit) {
if (isset($filtered[$commit->getPHID()])) {
unset($this->identifierMap[$name]);
}
}
}
}
private function shouldJoinAuditor() {
return ($this->auditIDs || $this->auditorPHIDs);
}
private function shouldJoinOwners() {
return (bool)$this->packagePHIDs;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$join = parent::buildJoinClauseParts($conn);
$audit_request = new PhabricatorRepositoryAuditRequest();
if ($this->shouldJoinAuditor()) {
$join[] = qsprintf(
$conn,
'JOIN %T auditor ON commit.phid = auditor.commitPHID',
$audit_request->getTableName());
}
if ($this->shouldJoinOwners()) {
$join[] = qsprintf(
$conn,
'JOIN %T package ON commit.phid = package.src
AND package.type = %s',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
DiffusionCommitHasPackageEdgeType::EDGECONST);
}
return $join;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinAuditor()) {
return true;
}
if ($this->shouldJoinOwners()) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'epoch' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'epoch',
'type' => 'int',
'reverse' => false,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'epoch' => (int)$object->getEpoch(),
);
}
public function getBuiltinOrders() {
$parent = parent::getBuiltinOrders();
// Rename the default ID-based orders.
$parent['importnew'] = array(
'name' => pht('Import Date (Newest First)'),
) + $parent['newest'];
$parent['importold'] = array(
'name' => pht('Import Date (Oldest First)'),
) + $parent['oldest'];
return array(
'newest' => array(
'vector' => array('epoch', 'id'),
'name' => pht('Commit Date (Newest First)'),
),
'oldest' => array(
'vector' => array('-epoch', '-id'),
'name' => pht('Commit Date (Oldest First)'),
),
) + $parent;
}
private function selectPossibleAuthors(array $phids) {
// See PHI1057. Select PHIDs which might possibly be commit authors from
// a larger list of PHIDs. This primarily filters out packages and projects
// from "Responsible Users: ..." queries. Our goal in performing this
// filtering is to improve the performance of the final query.
foreach ($phids as $key => $phid) {
if (phid_get_type($phid) !== PhabricatorPeopleUserPHIDType::TYPECONST) {
unset($phids[$key]);
}
}
return $phids;
}
}
diff --git a/src/applications/diffusion/query/DiffusionPullLogSearchEngine.php b/src/applications/diffusion/query/DiffusionPullLogSearchEngine.php
index dfdfceb519..dbb9205f61 100644
--- a/src/applications/diffusion/query/DiffusionPullLogSearchEngine.php
+++ b/src/applications/diffusion/query/DiffusionPullLogSearchEngine.php
@@ -1,186 +1,186 @@
<?php
final class DiffusionPullLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Pull Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return new PhabricatorRepositoryPullEventQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['pullerPHIDs']) {
$query->withPullerPHIDs($map['pullerPHIDs']);
}
if ($map['createdStart'] || $map['createdEnd']) {
$query->withEpochBetween(
$map['createdStart'],
$map['createdEnd']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setDatasource(new DiffusionRepositoryDatasource())
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setLabel(pht('Repositories'))
->setDescription(
pht('Search for pull logs for specific repositories.')),
id(new PhabricatorUsersSearchField())
->setKey('pullerPHIDs')
->setAliases(array('puller', 'pullers', 'pullerPHID'))
->setLabel(pht('Pullers'))
->setDescription(
pht('Search for pull logs by specific users.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function newExportFields() {
$viewer = $this->requireViewer();
$fields = array(
id(new PhabricatorPHIDExportField())
->setKey('repositoryPHID')
->setLabel(pht('Repository PHID')),
id(new PhabricatorStringExportField())
->setKey('repository')
->setLabel(pht('Repository')),
id(new PhabricatorPHIDExportField())
->setKey('pullerPHID')
->setLabel(pht('Puller PHID')),
id(new PhabricatorStringExportField())
->setKey('puller')
->setLabel(pht('Puller')),
id(new PhabricatorStringExportField())
->setKey('protocol')
->setLabel(pht('Protocol')),
id(new PhabricatorStringExportField())
->setKey('result')
->setLabel(pht('Result')),
id(new PhabricatorIntExportField())
->setKey('code')
->setLabel(pht('Code')),
id(new PhabricatorEpochExportField())
->setKey('date')
->setLabel(pht('Date')),
);
if ($viewer->getIsAdmin()) {
$fields[] = id(new PhabricatorStringExportField())
->setKey('remoteAddress')
->setLabel(pht('Remote Address'));
}
return $fields;
}
protected function newExportData(array $events) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($events as $event) {
if ($event->getPullerPHID()) {
$phids[] = $event->getPullerPHID();
}
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($events as $event) {
$repository = $event->getRepository();
if ($repository) {
$repository_phid = $repository->getPHID();
$repository_name = $repository->getDisplayName();
} else {
$repository_phid = null;
$repository_name = null;
}
$puller_phid = $event->getPullerPHID();
if ($puller_phid) {
$puller_name = $handles[$puller_phid]->getName();
} else {
$puller_name = null;
}
$map = array(
'repositoryPHID' => $repository_phid,
'repository' => $repository_name,
'pullerPHID' => $puller_phid,
'puller' => $puller_name,
'protocol' => $event->getRemoteProtocol(),
'result' => $event->getResultType(),
'code' => $event->getResultCode(),
'date' => $event->getEpoch(),
);
if ($viewer->getIsAdmin()) {
$map['remoteAddress'] = $event->getRemoteAddress();
}
$export[] = $map;
}
return $export;
}
protected function getURI($path) {
return '/diffusion/pulllog/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Pull Logs'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
$table = id(new DiffusionPullLogListView())
->setViewer($this->requireViewer())
->setLogs($logs);
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
}
diff --git a/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
index f41b6b89a4..d6877433f7 100644
--- a/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
+++ b/src/applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php
@@ -1,165 +1,165 @@
<?php
final class DiffusionRepositoryIdentitySearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Repository Identities');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return new PhabricatorRepositoryIdentityQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Matching Users'))
->setKey('effectivePHIDs')
->setAliases(
array(
'effective',
'effectivePHID',
))
->setDescription(pht('Search for identities by effective user.')),
id(new DiffusionIdentityAssigneeSearchField())
->setLabel(pht('Assigned To'))
->setKey('assignedPHIDs')
->setAliases(
array(
'assigned',
'assignedPHID',
))
->setDescription(pht('Search for identities by explicit assignee.')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Identity Contains'))
->setKey('match')
->setDescription(pht('Search for identities by substring.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Has Matching User'))
->setKey('hasEffectivePHID')
->setOptions(
pht('(Show All)'),
pht('Show Identities With Matching Users'),
pht('Show Identities Without Matching Users')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['hasEffectivePHID'] !== null) {
$query->withHasEffectivePHID($map['hasEffectivePHID']);
}
if ($map['match'] !== null) {
$query->withIdentityNameLike($map['match']);
}
if ($map['assignedPHIDs']) {
$query->withAssignedPHIDs($map['assignedPHIDs']);
}
if ($map['effectivePHIDs']) {
$query->withEffectivePHIDs($map['effectivePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/diffusion/identity/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Identities'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $identities,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($identities, 'PhabricatorRepositoryIdentity');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setViewer($viewer);
$phids = array();
foreach ($identities as $identity) {
$phids[] = $identity->getCurrentEffectiveUserPHID();
$phids[] = $identity->getManuallySetUserPHID();
}
$handles = $viewer->loadHandles($phids);
$unassigned = DiffusionIdentityUnassignedDatasource::FUNCTION_TOKEN;
foreach ($identities as $identity) {
$item = id(new PHUIObjectItemView())
->setObjectName($identity->getObjectName())
->setHeader($identity->getIdentityShortName())
->setHref($identity->getURI())
->setObject($identity);
$status_icon = 'fa-circle-o grey';
$effective_phid = $identity->getCurrentEffectiveUserPHID();
if ($effective_phid) {
$item->addIcon(
'fa-id-badge',
pht('Matches User: %s', $handles[$effective_phid]->getName()));
$status_icon = 'fa-id-badge';
}
$assigned_phid = $identity->getManuallySetUserPHID();
if ($assigned_phid) {
if ($assigned_phid === $unassigned) {
$item->addIcon(
'fa-ban',
pht('Explicitly Unassigned'));
$status_icon = 'fa-ban';
} else {
$item->addIcon(
'fa-user',
pht('Assigned To: %s', $handles[$assigned_phid]->getName()));
$status_icon = 'fa-user';
}
}
$item->setStatusIcon($status_icon);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No Identities found.'));
return $result;
}
}
diff --git a/src/applications/diffusion/query/DiffusionSyncLogSearchEngine.php b/src/applications/diffusion/query/DiffusionSyncLogSearchEngine.php
index 6b321189f4..02280efdd2 100644
--- a/src/applications/diffusion/query/DiffusionSyncLogSearchEngine.php
+++ b/src/applications/diffusion/query/DiffusionSyncLogSearchEngine.php
@@ -1,154 +1,154 @@
<?php
final class DiffusionSyncLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Sync Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return new PhabricatorRepositorySyncEventQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['createdStart'] || $map['createdEnd']) {
$query->withEpochBetween(
$map['createdStart'],
$map['createdEnd']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setDatasource(new DiffusionRepositoryDatasource())
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setLabel(pht('Repositories'))
->setDescription(
pht('Search for sync logs for specific repositories.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function newExportFields() {
$viewer = $this->requireViewer();
$fields = array(
id(new PhabricatorPHIDExportField())
->setKey('repositoryPHID')
->setLabel(pht('Repository PHID')),
id(new PhabricatorStringExportField())
->setKey('repository')
->setLabel(pht('Repository')),
id(new PhabricatorPHIDExportField())
->setKey('devicePHID')
->setLabel(pht('Device PHID')),
id(new PhabricatorPHIDExportField())
->setKey('fromDevicePHID')
->setLabel(pht('From Device PHID')),
id(new PhabricatorIntExportField())
->setKey('deviceVersion')
->setLabel(pht('Device Version')),
id(new PhabricatorIntExportField())
->setKey('fromDeviceVersion')
->setLabel(pht('From Device Version')),
id(new PhabricatorStringExportField())
->setKey('result')
->setLabel(pht('Result')),
id(new PhabricatorIntExportField())
->setKey('code')
->setLabel(pht('Code')),
id(new PhabricatorEpochExportField())
->setKey('date')
->setLabel(pht('Date')),
id(new PhabricatorIntExportField())
->setKey('syncWait')
->setLabel(pht('Sync Wait')),
);
return $fields;
}
protected function newExportData(array $events) {
$viewer = $this->requireViewer();
$export = array();
foreach ($events as $event) {
$repository = $event->getRepository();
$repository_phid = $repository->getPHID();
$repository_name = $repository->getDisplayName();
$map = array(
'repositoryPHID' => $repository_phid,
'repository' => $repository_name,
'devicePHID' => $event->getDevicePHID(),
'fromDevicePHID' => $event->getFromDevicePHID(),
'deviceVersion' => $event->getDeviceVersion(),
'fromDeviceVersion' => $event->getFromDeviceVersion(),
'result' => $event->getResultType(),
'code' => $event->getResultCode(),
'date' => $event->getEpoch(),
'syncWait' => $event->getSyncWait(),
);
$export[] = $map;
}
return $export;
}
protected function getURI($path) {
return '/diffusion/synclog/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Sync Logs'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
$table = id(new DiffusionSyncLogListView())
->setViewer($this->requireViewer())
->setLogs($logs);
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionAuditorDatasource.php b/src/applications/diffusion/typeahead/DiffusionAuditorDatasource.php
index 54c3aa72d9..fe0f12dd70 100644
--- a/src/applications/diffusion/typeahead/DiffusionAuditorDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionAuditorDatasource.php
@@ -1,26 +1,26 @@
<?php
final class DiffusionAuditorDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Auditors');
}
public function getPlaceholderText() {
return pht('Type a user, project or package name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
);
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php b/src/applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php
index 2bfc1ee037..eecef5dd03 100644
--- a/src/applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php
@@ -1,25 +1,25 @@
<?php
final class DiffusionAuditorFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Auditors');
}
public function getPlaceholderText() {
return pht('Type a user, project, package name or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectOrUserFunctionDatasource(),
new PhabricatorOwnersPackageFunctionDatasource(),
);
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php b/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php
index b69498931b..50ca68e59c 100644
--- a/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php
@@ -1,77 +1,77 @@
<?php
final class DiffusionIdentityUnassignedDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'unassigned()';
public function getBrowseTitle() {
return pht('Browse Explicitly Unassigned');
}
public function getPlaceholderText() {
return pht('Type "unassigned"...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getDatasourceFunctions() {
return array(
'unassigned' => array(
'name' => pht('Explicitly Unassigned'),
'summary' => pht('Find results which are not assigned.'),
'description' => pht(
"This function includes results which have been explicitly ".
"unassigned. Use a query like this to find explicitly ".
"unassigned results:\n\n%s\n\n".
"If you combine this function with other functions, the query will ".
"return results which match the other selectors //or// have no ".
"assignee. For example, this query will find results which are ".
"assigned to `alincoln`, and will also find results which have been ".
"unassigned:\n\n%s",
'> unassigned()',
'> alincoln, unassigned()'),
),
);
}
public function loadResults() {
$results = array(
$this->buildUnassignedResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = self::FUNCTION_TOKEN;
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildUnassignedResult());
}
return $results;
}
private function buildUnassignedResult() {
$name = pht('Unassigned');
return $this->newFunctionResult()
->setName($name.' unassigned')
->setDisplayName($name)
->setIcon('fa-ban')
->setPHID('unassigned()')
->setUnique(true)
->addAttribute(pht('Select results with no owner.'));
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionRefDatasource.php b/src/applications/diffusion/typeahead/DiffusionRefDatasource.php
index f98960e7cc..a0a8e89237 100644
--- a/src/applications/diffusion/typeahead/DiffusionRefDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionRefDatasource.php
@@ -1,50 +1,50 @@
<?php
final class DiffusionRefDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Branches');
}
public function getPlaceholderText() {
// TODO: This is really "branch, tag, bookmark or ref" but we are only
// using it to pick branches for now and sometimes the UI won't let you
// pick some of these types. See also "Browse Branches" above.
return pht('Type a branch name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$query = id(new PhabricatorRepositoryRefCursorQuery())
->withDatasourceQuery($raw_query);
$types = $this->getParameter('refTypes');
if ($types) {
$query->withRefTypes($types);
}
$repository_phids = $this->getParameter('repositoryPHIDs');
if ($repository_phids) {
$query->withRepositoryPHIDs($repository_phids);
}
$refs = $this->executeQuery($query);
$results = array();
foreach ($refs as $ref) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($ref->getRefName())
->setPHID($ref->getPHID());
}
return $results;
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionRepositoryDatasource.php b/src/applications/diffusion/typeahead/DiffusionRepositoryDatasource.php
index 5953dac8b3..5ba53d252c 100644
--- a/src/applications/diffusion/typeahead/DiffusionRepositoryDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionRepositoryDatasource.php
@@ -1,86 +1,86 @@
<?php
final class DiffusionRepositoryDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Repositories');
}
public function getPlaceholderText() {
return pht('Type a repository name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function loadResults() {
$query = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer());
$this->applyFerretConstraints(
$query,
id(new PhabricatorRepository())->newFerretEngine(),
'title',
$this->getRawQuery());
$repos = $query->execute();
$type_icon = id(new PhabricatorRepositoryRepositoryPHIDType())
->getTypeIcon();
$image_sprite =
"phabricator-search-icon phui-font-fa phui-icon-view {$type_icon}";
$results = array();
foreach ($repos as $repository) {
$monogram = $repository->getMonogram();
$name = $repository->getName();
$display_name = "{$monogram} {$name}";
$parts = array();
$parts[] = $name;
$slug = $repository->getRepositorySlug();
if (phutil_nonempty_string($slug)) {
$parts[] = $slug;
}
$callsign = $repository->getCallsign();
if ($callsign) {
$parts[] = $callsign;
}
foreach ($repository->getAllMonograms() as $monogram) {
$parts[] = $monogram;
}
$name = implode("\n", $parts);
$vcs = $repository->getVersionControlSystem();
$vcs_type = PhabricatorRepositoryType::getNameForRepositoryType($vcs);
$result = id(new PhabricatorTypeaheadResult())
->setName($name)
->setDisplayName($display_name)
->setURI($repository->getURI())
->setPHID($repository->getPHID())
->setPriorityString($repository->getMonogram())
->setPriorityType('repo')
->setImageSprite($image_sprite)
->setDisplayType(pht('Repository'))
->addAttribute($vcs_type);
if (!$repository->isTracked()) {
$result->setClosed(pht('Inactive'));
}
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php b/src/applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php
index 5fb7d5f5ac..5865aa0ef4 100644
--- a/src/applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php
@@ -1,25 +1,25 @@
<?php
final class DiffusionRepositoryFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Repositories');
}
public function getPlaceholderText() {
return pht('Type a repository name or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDifferentialApplication';
+ return PhabricatorDifferentialApplication::class;
}
public function getComponentDatasources() {
return array(
new DiffusionTaggedRepositoriesFunctionDatasource(),
new DiffusionRepositoryDatasource(),
);
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionSymbolDatasource.php b/src/applications/diffusion/typeahead/DiffusionSymbolDatasource.php
index 1c29c0dde4..1382bd41e0 100644
--- a/src/applications/diffusion/typeahead/DiffusionSymbolDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionSymbolDatasource.php
@@ -1,60 +1,60 @@
<?php
final class DiffusionSymbolDatasource
extends PhabricatorTypeaheadDatasource {
public function isBrowsable() {
// This is slightly involved to make browsable, and browsing symbols
// does not seem likely to be very useful in any real software project.
return false;
}
public function getBrowseTitle() {
return pht('Browse Symbols');
}
public function getPlaceholderText() {
return pht('Type a symbol name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
if (strlen($raw_query)) {
$symbols = id(new DiffusionSymbolQuery())
->setViewer($viewer)
->setNamePrefix($raw_query)
->setLimit(15)
->needRepositories(true)
->needPaths(true)
->execute();
foreach ($symbols as $symbol) {
$lang = $symbol->getSymbolLanguage();
$name = $symbol->getSymbolName();
$type = $symbol->getSymbolType();
$repo = $symbol->getRepository()->getName();
$results[] = id(new PhabricatorTypeaheadResult())
->setName($name)
->setURI($symbol->getURI())
->setPHID(md5($symbol->getURI())) // Just needs to be unique.
->setDisplayName($name)
->setDisplayType(strtoupper($lang).' '.ucwords($type).' ('.$repo.')')
->setPriorityType('symb')
->setImageSprite(
'phabricator-search-icon phui-font-fa phui-icon-view fa-code '.
'lightgreytext');
}
}
return $results;
}
}
diff --git a/src/applications/diffusion/typeahead/DiffusionTaggedRepositoriesFunctionDatasource.php b/src/applications/diffusion/typeahead/DiffusionTaggedRepositoriesFunctionDatasource.php
index 019d78d786..dbc7362b2a 100644
--- a/src/applications/diffusion/typeahead/DiffusionTaggedRepositoriesFunctionDatasource.php
+++ b/src/applications/diffusion/typeahead/DiffusionTaggedRepositoriesFunctionDatasource.php
@@ -1,111 +1,111 @@
<?php
final class DiffusionTaggedRepositoriesFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Repositories');
}
public function getPlaceholderText() {
return pht('Type tagged(<project>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'tagged' => array(
'name' => pht('Repositories: ...'),
'arguments' => pht('project'),
'summary' => pht('Find results for repositories of a project.'),
'description' => pht(
'This function allows you to find results for any of the `.
`repositories of a project:'.
"\n\n".
'> tagged(engineering)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setColor(null)
->setPHID('tagged('.$result->getPHID().')')
->setDisplayName(pht('Tagged: %s', $result->getDisplayName()))
->setName('tagged '.$result->getName())
->resetAttributes()
->addAttribute(pht('Function'))
->addAttribute(pht('Select repositories tagged with this project.'));
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_OR,
$phids)
->execute();
$results = array();
foreach ($repositories as $repository) {
$results[] = $repository->getPHID();
}
if (!$results) {
// TODO: This is a little hacky, but if you query for "tagged(x)" and
// there are no such repositories, we want to match nothing. If we
// just return `array()`, that gets evaluated as "no constraint" and
// we match everything. This works correctly for now, but should be
// replaced with some more elegant/general approach eventually.
$results[] = PhabricatorPHIDConstants::PHID_VOID;
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
// Remove any project color on this token.
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht('Repositories: Invalid Project'));
} else {
$token
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setKey('tagged('.$token->getKey().')')
->setValue(pht('Tagged: %s', $token->getValue()));
}
}
return $tokens;
}
}
diff --git a/src/applications/diviner/editor/DivinerLiveBookEditor.php b/src/applications/diviner/editor/DivinerLiveBookEditor.php
index 3f392391bb..dea16af377 100644
--- a/src/applications/diviner/editor/DivinerLiveBookEditor.php
+++ b/src/applications/diviner/editor/DivinerLiveBookEditor.php
@@ -1,23 +1,23 @@
<?php
final class DivinerLiveBookEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Diviner Books');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/diviner/phid/DivinerAtomPHIDType.php b/src/applications/diviner/phid/DivinerAtomPHIDType.php
index 7387b0cafe..3e040a9e79 100644
--- a/src/applications/diviner/phid/DivinerAtomPHIDType.php
+++ b/src/applications/diviner/phid/DivinerAtomPHIDType.php
@@ -1,53 +1,53 @@
<?php
final class DivinerAtomPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ATOM';
public function getTypeName() {
return pht('Diviner Atom');
}
public function newObject() {
return new DivinerLiveSymbol();
}
public function getTypeIcon() {
return 'fa-cube';
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DivinerAtomQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$atom = $objects[$phid];
$book = $atom->getBook()->getName();
$name = $atom->getName();
$type = $atom->getType();
$handle
->setName($atom->getName())
->setTitle($atom->getTitle())
->setURI("/book/{$book}/{$type}/{$name}/")
->setStatus($atom->getGraphHash()
? PhabricatorObjectHandle::STATUS_OPEN
: PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
diff --git a/src/applications/diviner/phid/DivinerBookPHIDType.php b/src/applications/diviner/phid/DivinerBookPHIDType.php
index da08ae3e87..bb840c5342 100644
--- a/src/applications/diviner/phid/DivinerBookPHIDType.php
+++ b/src/applications/diviner/phid/DivinerBookPHIDType.php
@@ -1,48 +1,48 @@
<?php
final class DivinerBookPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'BOOK';
public function getTypeName() {
return pht('Diviner Book');
}
public function newObject() {
return new DivinerLiveBook();
}
public function getTypeIcon() {
return 'fa-book';
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DivinerBookQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$book = $objects[$phid];
$name = $book->getName();
$handle
->setName($book->getShortTitle())
->setFullName($book->getTitle())
->setURI("/book/{$name}/");
}
}
}
diff --git a/src/applications/diviner/query/DivinerAtomQuery.php b/src/applications/diviner/query/DivinerAtomQuery.php
index 65a5634008..1ca7aad984 100644
--- a/src/applications/diviner/query/DivinerAtomQuery.php
+++ b/src/applications/diviner/query/DivinerAtomQuery.php
@@ -1,511 +1,511 @@
<?php
final class DivinerAtomQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $bookPHIDs;
private $names;
private $types;
private $contexts;
private $indexes;
private $isDocumentable;
private $isGhost;
private $nodeHashes;
private $titles;
private $nameContains;
private $repositoryPHIDs;
private $needAtoms;
private $needExtends;
private $needChildren;
private $needRepositories;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBookPHIDs(array $phids) {
$this->bookPHIDs = $phids;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withContexts(array $contexts) {
$this->contexts = $contexts;
return $this;
}
public function withIndexes(array $indexes) {
$this->indexes = $indexes;
return $this;
}
public function withNodeHashes(array $hashes) {
$this->nodeHashes = $hashes;
return $this;
}
public function withTitles($titles) {
$this->titles = $titles;
return $this;
}
public function withNameContains($text) {
$this->nameContains = $text;
return $this;
}
public function needAtoms($need) {
$this->needAtoms = $need;
return $this;
}
public function needChildren($need) {
$this->needChildren = $need;
return $this;
}
/**
* Include or exclude "ghosts", which are symbols which used to exist but do
* not exist currently (for example, a function which existed in an older
* version of the codebase but was deleted).
*
* These symbols had PHIDs assigned to them, and may have other sorts of
* metadata that we don't want to lose (like comments or flags), so we don't
* delete them outright. They might also come back in the future: the change
* which deleted the symbol might be reverted, or the documentation might
* have been generated incorrectly by accident. In these cases, we can
* restore the original data.
*
* @param bool
* @return this
*/
public function withGhosts($ghosts) {
$this->isGhost = $ghosts;
return $this;
}
public function needExtends($need) {
$this->needExtends = $need;
return $this;
}
public function withIsDocumentable($documentable) {
$this->isDocumentable = $documentable;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function needRepositories($need_repositories) {
$this->needRepositories = $need_repositories;
return $this;
}
protected function loadPage() {
$table = new DivinerLiveSymbol();
$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 willFilterPage(array $atoms) {
assert_instances_of($atoms, 'DivinerLiveSymbol');
$books = array_unique(mpull($atoms, 'getBookPHID'));
$books = id(new DivinerBookQuery())
->setViewer($this->getViewer())
->withPHIDs($books)
->execute();
$books = mpull($books, null, 'getPHID');
foreach ($atoms as $key => $atom) {
$book = idx($books, $atom->getBookPHID());
if (!$book) {
$this->didRejectResult($atom);
unset($atoms[$key]);
continue;
}
$atom->attachBook($book);
}
if ($this->needAtoms) {
$atom_data = id(new DivinerLiveAtom())->loadAllWhere(
'symbolPHID IN (%Ls)',
mpull($atoms, 'getPHID'));
$atom_data = mpull($atom_data, null, 'getSymbolPHID');
foreach ($atoms as $key => $atom) {
$data = idx($atom_data, $atom->getPHID());
$atom->attachAtom($data);
}
}
// Load all of the symbols this symbol extends, recursively. Commonly,
// this means all the ancestor classes and interfaces it extends and
// implements.
if ($this->needExtends) {
// First, load all the matching symbols by name. This does 99% of the
// work in most cases, assuming things are named at all reasonably.
$names = array();
foreach ($atoms as $atom) {
if (!$atom->getAtom()) {
continue;
}
foreach ($atom->getAtom()->getExtends() as $xref) {
$names[] = $xref->getName();
}
}
if ($names) {
$xatoms = id(new DivinerAtomQuery())
->setViewer($this->getViewer())
->withNames($names)
->withGhosts(false)
->needExtends(true)
->needAtoms(true)
->needChildren($this->needChildren)
->execute();
$xatoms = mgroup($xatoms, 'getName', 'getType', 'getBookPHID');
} else {
$xatoms = array();
}
foreach ($atoms as $atom) {
$atom_lang = null;
$atom_extends = array();
if ($atom->getAtom()) {
$atom_lang = $atom->getAtom()->getLanguage();
$atom_extends = $atom->getAtom()->getExtends();
}
$extends = array();
foreach ($atom_extends as $xref) {
// If there are no symbols of the matching name and type, we can't
// resolve this.
if (empty($xatoms[$xref->getName()][$xref->getType()])) {
continue;
}
// If we found matches in the same documentation book, prefer them
// over other matches. Otherwise, look at all the matches.
$matches = $xatoms[$xref->getName()][$xref->getType()];
if (isset($matches[$atom->getBookPHID()])) {
$maybe = $matches[$atom->getBookPHID()];
} else {
$maybe = array_mergev($matches);
}
if (!$maybe) {
continue;
}
// Filter out matches in a different language, since, e.g., PHP
// classes can not implement JS classes.
$same_lang = array();
foreach ($maybe as $xatom) {
if ($xatom->getAtom()->getLanguage() == $atom_lang) {
$same_lang[] = $xatom;
}
}
if (!$same_lang) {
continue;
}
// If we have duplicates remaining, just pick the first one. There's
// nothing more we can do to figure out which is the real one.
$extends[] = head($same_lang);
}
$atom->attachExtends($extends);
}
}
if ($this->needChildren) {
$child_hashes = $this->getAllChildHashes($atoms, $this->needExtends);
if ($child_hashes) {
$children = id(new DivinerAtomQuery())
->setViewer($this->getViewer())
->withNodeHashes($child_hashes)
->needAtoms($this->needAtoms)
->execute();
$children = mpull($children, null, 'getNodeHash');
} else {
$children = array();
}
$this->attachAllChildren($atoms, $children, $this->needExtends);
}
if ($this->needRepositories) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($atoms, 'getRepositoryPHID'))
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($atoms as $key => $atom) {
if ($atom->getRepositoryPHID() === null) {
$atom->attachRepository(null);
continue;
}
$repository = idx($repositories, $atom->getRepositoryPHID());
if (!$repository) {
$this->didRejectResult($atom);
unset($atom[$key]);
continue;
}
$atom->attachRepository($repository);
}
}
return $atoms;
}
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->bookPHIDs) {
$where[] = qsprintf(
$conn,
'bookPHID IN (%Ls)',
$this->bookPHIDs);
}
if ($this->types) {
$where[] = qsprintf(
$conn,
'type IN (%Ls)',
$this->types);
}
if ($this->names) {
$where[] = qsprintf(
$conn,
'name IN (%Ls)',
$this->names);
}
if ($this->titles) {
$hashes = array();
foreach ($this->titles as $title) {
$slug = DivinerAtomRef::normalizeTitleString($title);
$hash = PhabricatorHash::digestForIndex($slug);
$hashes[] = $hash;
}
$where[] = qsprintf(
$conn,
'titleSlugHash in (%Ls)',
$hashes);
}
if ($this->contexts) {
$with_null = false;
$contexts = $this->contexts;
foreach ($contexts as $key => $value) {
if ($value === null) {
unset($contexts[$key]);
$with_null = true;
continue;
}
}
if ($contexts && $with_null) {
$where[] = qsprintf(
$conn,
'context IN (%Ls) OR context IS NULL',
$contexts);
} else if ($contexts) {
$where[] = qsprintf(
$conn,
'context IN (%Ls)',
$contexts);
} else if ($with_null) {
$where[] = qsprintf(
$conn,
'context IS NULL');
}
}
if ($this->indexes) {
$where[] = qsprintf(
$conn,
'atomIndex IN (%Ld)',
$this->indexes);
}
if ($this->isDocumentable !== null) {
$where[] = qsprintf(
$conn,
'isDocumentable = %d',
(int)$this->isDocumentable);
}
if ($this->isGhost !== null) {
if ($this->isGhost) {
$where[] = qsprintf($conn, 'graphHash IS NULL');
} else {
$where[] = qsprintf($conn, 'graphHash IS NOT NULL');
}
}
if ($this->nodeHashes) {
$where[] = qsprintf(
$conn,
'nodeHash IN (%Ls)',
$this->nodeHashes);
}
if ($this->nameContains) {
// NOTE: This `CONVERT()` call makes queries case-insensitive, since
// the column has binary collation. Eventually, this should move into
// fulltext.
$where[] = qsprintf(
$conn,
'CONVERT(name USING utf8) LIKE %~',
$this->nameContains);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
/**
* Walk a list of atoms and collect all the node hashes of the atoms'
* children. When recursing, also walk up the tree and collect children of
* atoms they extend.
*
* @param list<DivinerLiveSymbol> List of symbols to collect child hashes of.
* @param bool True to collect children of extended atoms,
* as well.
* @return map<string, string> Hashes of atoms' children.
*/
private function getAllChildHashes(array $symbols, $recurse_up) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
$hashes = array();
foreach ($symbols as $symbol) {
$child_hashes = array();
if ($symbol->getAtom()) {
$child_hashes = $symbol->getAtom()->getChildHashes();
}
foreach ($child_hashes as $hash) {
$hashes[$hash] = $hash;
}
if ($recurse_up) {
$hashes += $this->getAllChildHashes($symbol->getExtends(), true);
}
}
return $hashes;
}
/**
* Attach child atoms to existing atoms. In recursive mode, also attach child
* atoms to atoms that these atoms extend.
*
* @param list<DivinerLiveSymbol> List of symbols to attach children to.
* @param map<string, DivinerLiveSymbol> Map of symbols, keyed by node hash.
* @param bool True to attach children to extended atoms, as well.
* @return void
*/
private function attachAllChildren(
array $symbols,
array $children,
$recurse_up) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
assert_instances_of($children, 'DivinerLiveSymbol');
foreach ($symbols as $symbol) {
$child_hashes = array();
$symbol_children = array();
if ($symbol->getAtom()) {
$child_hashes = $symbol->getAtom()->getChildHashes();
}
foreach ($child_hashes as $hash) {
if (isset($children[$hash])) {
$symbol_children[] = $children[$hash];
}
}
$symbol->attachChildren($symbol_children);
if ($recurse_up) {
$this->attachAllChildren($symbol->getExtends(), $children, true);
}
}
}
public function getQueryApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
}
diff --git a/src/applications/diviner/query/DivinerAtomSearchEngine.php b/src/applications/diviner/query/DivinerAtomSearchEngine.php
index 35caf20a63..47dd418c78 100644
--- a/src/applications/diviner/query/DivinerAtomSearchEngine.php
+++ b/src/applications/diviner/query/DivinerAtomSearchEngine.php
@@ -1,158 +1,158 @@
<?php
final class DivinerAtomSearchEngine extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Documentation Atoms');
}
public function getApplicationClassName() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'bookPHIDs',
$this->readPHIDsFromRequest($request, 'bookPHIDs'));
$saved->setParameter(
'repositoryPHIDs',
$this->readPHIDsFromRequest($request, 'repositoryPHIDs'));
$saved->setParameter('name', $request->getStr('name'));
$saved->setParameter(
'types',
$this->readListFromRequest($request, 'types'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new DivinerAtomQuery());
$books = $saved->getParameter('bookPHIDs');
if ($books) {
$query->withBookPHIDs($books);
}
$repository_phids = $saved->getParameter('repositoryPHIDs');
if ($repository_phids) {
$query->withRepositoryPHIDs($repository_phids);
}
$name = $saved->getParameter('name');
if ($name) {
$query->withNameContains($name);
}
$types = $saved->getParameter('types');
if ($types) {
$query->withTypes($types);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$form->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name Contains'))
->setName('name')
->setValue($saved->getParameter('name')));
$all_types = array();
foreach (DivinerAtom::getAllTypes() as $type) {
$all_types[$type] = DivinerAtom::getAtomTypeNameString($type);
}
asort($all_types);
$types = $saved->getParameter('types', array());
$types = array_fuse($types);
$type_control = id(new AphrontFormCheckboxControl())
->setLabel(pht('Types'));
foreach ($all_types as $type => $name) {
$type_control->addCheckbox(
'types[]',
$type,
$name,
isset($types[$type]));
}
$form->appendChild($type_control);
$form->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new DivinerBookDatasource())
->setName('bookPHIDs')
->setLabel(pht('Books'))
->setValue($saved->getParameter('bookPHIDs')));
$form->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Repositories'))
->setName('repositoryPHIDs')
->setDatasource(new DiffusionRepositoryDatasource())
->setValue($saved->getParameter('repositoryPHIDs')));
}
protected function getURI($path) {
return '/diviner/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Atoms'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $symbols,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($symbols as $symbol) {
$type = $symbol->getType();
$type_name = DivinerAtom::getAtomTypeNameString($type);
$item = id(new PHUIObjectItemView())
->setHeader($symbol->getTitle())
->setHref($symbol->getURI())
->addAttribute($symbol->getSummary())
->addIcon('none', $type_name);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No books found.'));
return $result;
}
}
diff --git a/src/applications/diviner/query/DivinerBookQuery.php b/src/applications/diviner/query/DivinerBookQuery.php
index e809099c7e..4bc9ff270d 100644
--- a/src/applications/diviner/query/DivinerBookQuery.php
+++ b/src/applications/diviner/query/DivinerBookQuery.php
@@ -1,200 +1,200 @@
<?php
final class DivinerBookQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $names;
private $nameLike;
private $namePrefix;
private $repositoryPHIDs;
private $needProjectPHIDs;
private $needRepositories;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNameLike($name) {
$this->nameLike = $name;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNamePrefix($prefix) {
$this->namePrefix = $prefix;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function needProjectPHIDs($need_phids) {
$this->needProjectPHIDs = $need_phids;
return $this;
}
public function needRepositories($need_repositories) {
$this->needRepositories = $need_repositories;
return $this;
}
protected function loadPage() {
$table = new DivinerLiveBook();
$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 didFilterPage(array $books) {
assert_instances_of($books, 'DivinerLiveBook');
if ($this->needRepositories) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($books, 'getRepositoryPHID'))
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($books as $key => $book) {
if ($book->getRepositoryPHID() === null) {
$book->attachRepository(null);
continue;
}
$repository = idx($repositories, $book->getRepositoryPHID());
if (!$repository) {
$this->didRejectResult($book);
unset($books[$key]);
continue;
}
$book->attachRepository($repository);
}
}
if ($this->needProjectPHIDs) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($books, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($books as $book) {
$project_phids = $edge_query->getDestinationPHIDs(
array(
$book->getPHID(),
));
$book->attachProjectPHIDs($project_phids);
}
}
return $books;
}
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 (phutil_nonempty_string($this->nameLike)) {
$where[] = qsprintf(
$conn,
'name LIKE %~',
$this->nameLike);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'name IN (%Ls)',
$this->names);
}
if (phutil_nonempty_string($this->namePrefix)) {
$where[] = qsprintf(
$conn,
'name LIKE %>',
$this->namePrefix);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'column' => 'name',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
}
diff --git a/src/applications/diviner/typeahead/DivinerBookDatasource.php b/src/applications/diviner/typeahead/DivinerBookDatasource.php
index 2584626d6e..8fc2a52238 100644
--- a/src/applications/diviner/typeahead/DivinerBookDatasource.php
+++ b/src/applications/diviner/typeahead/DivinerBookDatasource.php
@@ -1,37 +1,37 @@
<?php
final class DivinerBookDatasource extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Books');
}
public function getPlaceholderText() {
return pht('Type a book name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDivinerApplication';
+ return PhabricatorDivinerApplication::class;
}
public function loadResults() {
$raw_query = $this->getRawQuery();
$query = id(new DivinerBookQuery())
->setOrder('name')
->withNamePrefix($raw_query);
$books = $this->executeQuery($query);
$results = array();
foreach ($books as $book) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($book->getTitle())
->setURI('/book/'.$book->getName().'/')
->setPHID($book->getPHID())
->setPriorityString($book->getName());
}
return $results;
}
}
diff --git a/src/applications/doorkeeper/phid/DoorkeeperExternalObjectPHIDType.php b/src/applications/doorkeeper/phid/DoorkeeperExternalObjectPHIDType.php
index be9e32cf2a..1817e97b37 100644
--- a/src/applications/doorkeeper/phid/DoorkeeperExternalObjectPHIDType.php
+++ b/src/applications/doorkeeper/phid/DoorkeeperExternalObjectPHIDType.php
@@ -1,47 +1,47 @@
<?php
final class DoorkeeperExternalObjectPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'XOBJ';
public function getTypeName() {
return pht('External Object');
}
public function newObject() {
return new DoorkeeperExternalObject();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDoorkeeperApplication';
+ return PhabricatorDoorkeeperApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DoorkeeperExternalObjectQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$xobj = $objects[$phid];
$uri = $xobj->getObjectURI();
$name = $xobj->getDisplayName();
$full_name = $xobj->getDisplayFullName();
$handle
->setURI($uri)
->setName($name)
->setFullName($full_name);
}
}
}
diff --git a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
index 2a33206831..c9a7c140eb 100644
--- a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
+++ b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
@@ -1,47 +1,47 @@
<?php
final class DoorkeeperExternalObjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
protected $phids;
protected $objectKeys;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectKeys(array $keys) {
$this->objectKeys = $keys;
return $this;
}
public function newResultObject() {
return new DoorkeeperExternalObject();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->objectKeys !== null) {
$where[] = qsprintf(
$conn,
'objectKey IN (%Ls)',
$this->objectKeys);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDoorkeeperApplication';
+ return PhabricatorDoorkeeperApplication::class;
}
}
diff --git a/src/applications/drydock/editor/DrydockBlueprintEditEngine.php b/src/applications/drydock/editor/DrydockBlueprintEditEngine.php
index a3b6fdaf75..e01513f2b9 100644
--- a/src/applications/drydock/editor/DrydockBlueprintEditEngine.php
+++ b/src/applications/drydock/editor/DrydockBlueprintEditEngine.php
@@ -1,173 +1,173 @@
<?php
final class DrydockBlueprintEditEngine
extends PhabricatorEditEngine {
private $blueprintImplementation;
const ENGINECONST = 'drydock.blueprint';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Drydock Blueprints');
}
public function getSummaryHeader() {
return pht('Edit Drydock Blueprint Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Drydock blueprints.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function setBlueprintImplementation(
DrydockBlueprintImplementation $impl) {
$this->blueprintImplementation = $impl;
return $this;
}
public function getBlueprintImplementation() {
return $this->blueprintImplementation;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$blueprint = DrydockBlueprint::initializeNewBlueprint($viewer);
$impl = $this->getBlueprintImplementation();
if ($impl) {
$blueprint
->setClassName(get_class($impl))
->attachImplementation(clone $impl);
}
return $blueprint;
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$type = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'type') {
continue;
}
$type = $raw_xaction['value'];
}
if ($type === null) {
throw new Exception(
pht(
'When creating a new Drydock blueprint via the Conduit API, you '.
'must provide a "type" transaction to select a type.'));
}
$map = DrydockBlueprintImplementation::getAllBlueprintImplementations();
if (!isset($map[$type])) {
throw new Exception(
pht(
'Blueprint type "%s" is unrecognized. Valid types are: %s.',
$type,
implode(', ', array_keys($map))));
}
$impl = clone $map[$type];
$this->setBlueprintImplementation($impl);
return $this->newEditableObject();
}
protected function newEditableObjectForDocumentation() {
// In order to generate the proper list of fields/transactions for a
// blueprint, a blueprint's type needs to be known upfront, and there's
// currently no way to pre-specify the type. Hardcoding an implementation
// here prevents the fatal on the Conduit API page and allows transactions
// to be edited.
$impl = new DrydockWorkingCopyBlueprintImplementation();
$this->setBlueprintImplementation($impl);
return $this->newEditableObject();
}
protected function newObjectQuery() {
return new DrydockBlueprintQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Blueprint');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Blueprint');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Blueprint: %s', $object->getBlueprintName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Blueprint');
}
protected function getObjectCreateShortText() {
return pht('Create Blueprint');
}
protected function getObjectName() {
return pht('Blueprint');
}
protected function getEditorURI() {
return '/drydock/blueprint/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/drydock/blueprint/';
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return "/drydock/blueprint/{$id}/";
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
DrydockCreateBlueprintsCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$impl = $object->getImplementation();
return array(
// This field appears in the web UI
id(new PhabricatorStaticEditField())
->setKey('displayType')
->setLabel(pht('Blueprint Type'))
->setDescription(pht('Type of blueprint.'))
->setValue($impl->getBlueprintName()),
id(new PhabricatorTextEditField())
->setKey('type')
->setLabel(pht('Type'))
->setIsFormField(false)
->setTransactionType(
DrydockBlueprintTypeTransaction::TRANSACTIONTYPE)
->setDescription(pht('When creating a blueprint, set the type.'))
->setConduitDescription(pht('Set the blueprint type.'))
->setConduitTypeDescription(pht('Blueprint type.'))
->setValue($object->getClassName()),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the blueprint.'))
->setTransactionType(DrydockBlueprintNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getBlueprintName()),
);
}
}
diff --git a/src/applications/drydock/editor/DrydockBlueprintEditor.php b/src/applications/drydock/editor/DrydockBlueprintEditor.php
index aac3e7a020..f07907147c 100644
--- a/src/applications/drydock/editor/DrydockBlueprintEditor.php
+++ b/src/applications/drydock/editor/DrydockBlueprintEditor.php
@@ -1,35 +1,35 @@
<?php
final class DrydockBlueprintEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Drydock Blueprints');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this blueprint.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php b/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php
index 058ccff6a9..61495b73e4 100644
--- a/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php
+++ b/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class DrydockAuthorizationPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DRYA';
public function getTypeName() {
return pht('Drydock Authorization');
}
public function newObject() {
return new DrydockAuthorization();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DrydockAuthorizationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$authorization = $objects[$phid];
$id = $authorization->getID();
$handle->setName(pht('Drydock Authorization %d', $id));
$handle->setURI("/drydock/authorization/{$id}/");
}
}
}
diff --git a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php
index ef286cf5f1..e363704454 100644
--- a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php
+++ b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php
@@ -1,48 +1,48 @@
<?php
final class DrydockBlueprintPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DRYB';
public function getTypeName() {
return pht('Blueprint');
}
public function getTypeIcon() {
return 'fa-map-o';
}
public function newObject() {
return new DrydockBlueprint();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DrydockBlueprintQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$blueprint = $objects[$phid];
$id = $blueprint->getID();
$name = $blueprint->getBlueprintName();
$handle
->setName($name)
->setFullName(pht('Blueprint %d: %s', $id, $name))
->setURI("/drydock/blueprint/{$id}/");
}
}
}
diff --git a/src/applications/drydock/phid/DrydockLeasePHIDType.php b/src/applications/drydock/phid/DrydockLeasePHIDType.php
index faa751b0f1..51d6a6e31a 100644
--- a/src/applications/drydock/phid/DrydockLeasePHIDType.php
+++ b/src/applications/drydock/phid/DrydockLeasePHIDType.php
@@ -1,47 +1,47 @@
<?php
final class DrydockLeasePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DRYL';
public function getTypeName() {
return pht('Drydock Lease');
}
public function getTypeIcon() {
return 'fa-link';
}
public function newObject() {
return new DrydockLease();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DrydockLeaseQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$lease = $objects[$phid];
$id = $lease->getID();
$handle->setName(pht(
'Lease %d',
$id));
$handle->setURI("/drydock/lease/{$id}/");
}
}
}
diff --git a/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php b/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php
index 6222552f84..35c78b5e03 100644
--- a/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php
+++ b/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class DrydockRepositoryOperationPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DRYO';
public function getTypeName() {
return pht('Repository Operation');
}
public function newObject() {
return new DrydockRepositoryOperation();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DrydockRepositoryOperationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$operation = $objects[$phid];
$id = $operation->getID();
$handle->setName(pht('Repository Operation %d', $id));
$handle->setURI("/drydock/operation/{$id}/");
}
}
}
diff --git a/src/applications/drydock/phid/DrydockResourcePHIDType.php b/src/applications/drydock/phid/DrydockResourcePHIDType.php
index a36647964d..8ca8718e6e 100644
--- a/src/applications/drydock/phid/DrydockResourcePHIDType.php
+++ b/src/applications/drydock/phid/DrydockResourcePHIDType.php
@@ -1,50 +1,50 @@
<?php
final class DrydockResourcePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'DRYR';
public function getTypeName() {
return pht('Drydock Resource');
}
public function getTypeIcon() {
return 'fa-map';
}
public function newObject() {
return new DrydockResource();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DrydockResourceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$resource = $objects[$phid];
$id = $resource->getID();
$handle->setName(
pht(
'Resource %d: %s',
$id,
$resource->getResourceName()));
$handle->setURI("/drydock/resource/{$id}/");
}
}
}
diff --git a/src/applications/drydock/query/DrydockAuthorizationSearchEngine.php b/src/applications/drydock/query/DrydockAuthorizationSearchEngine.php
index 16737a9dfe..81e8c00ba0 100644
--- a/src/applications/drydock/query/DrydockAuthorizationSearchEngine.php
+++ b/src/applications/drydock/query/DrydockAuthorizationSearchEngine.php
@@ -1,120 +1,120 @@
<?php
final class DrydockAuthorizationSearchEngine
extends PhabricatorApplicationSearchEngine {
private $blueprint;
public function setBlueprint(DrydockBlueprint $blueprint) {
$this->blueprint = $blueprint;
return $this;
}
public function getBlueprint() {
return $this->blueprint;
}
public function getResultTypeDescription() {
return pht('Drydock Authorizations');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
$query = new DrydockAuthorizationQuery();
$blueprint = $this->getBlueprint();
if ($blueprint) {
$query->withBlueprintPHIDs(array($blueprint->getPHID()));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['blueprintPHIDs']) {
$query->withBlueprintPHIDs($map['blueprintPHIDs']);
}
if ($map['objectPHIDs']) {
$query->withObjectPHIDs($map['objectPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Blueprints'))
->setKey('blueprintPHIDs')
->setConduitParameterType(new ConduitPHIDListParameterType())
->setDescription(pht('Search authorizations for specific blueprints.'))
->setAliases(array('blueprint', 'blueprints'))
->setDatasource(new DrydockBlueprintDatasource()),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Objects'))
->setKey('objectPHIDs')
->setDescription(pht('Search authorizations from specific objects.'))
->setAliases(array('object', 'objects')),
);
}
protected function getHiddenFields() {
return array(
'blueprintPHIDs',
'objectPHIDs',
);
}
protected function getURI($path) {
$blueprint = $this->getBlueprint();
if (!$blueprint) {
throw new PhutilInvalidStateException('setBlueprint');
}
$id = $blueprint->getID();
return "/drydock/blueprint/{$id}/authorizations/".$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Authorizations'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $authorizations,
PhabricatorSavedQuery $query,
array $handles) {
$list = id(new DrydockAuthorizationListView())
->setUser($this->requireViewer())
->setAuthorizations($authorizations);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($list);
return $result;
}
}
diff --git a/src/applications/drydock/query/DrydockBlueprintSearchEngine.php b/src/applications/drydock/query/DrydockBlueprintSearchEngine.php
index 3c80ca2700..244afcb986 100644
--- a/src/applications/drydock/query/DrydockBlueprintSearchEngine.php
+++ b/src/applications/drydock/query/DrydockBlueprintSearchEngine.php
@@ -1,141 +1,141 @@
<?php
final class DrydockBlueprintSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Drydock Blueprints');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function newQuery() {
return id(new DrydockBlueprintQuery());
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['isDisabled'] !== null) {
$query->withDisabled($map['isDisabled']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for blueprints by name substring.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Disabled'))
->setKey('isDisabled')
->setOptions(
pht('(Show All)'),
pht('Show Only Disabled Blueprints'),
pht('Hide Disabled Blueprints')),
);
}
protected function getURI($path) {
return '/drydock/blueprint/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'active' => pht('Active Blueprints'),
'all' => pht('All Blueprints'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter('isDisabled', false);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $blueprints,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($blueprints, 'DrydockBlueprint');
$viewer = $this->requireViewer();
if ($blueprints) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($blueprints, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
}
$view = new PHUIObjectItemListView();
foreach ($blueprints as $blueprint) {
$impl = $blueprint->getImplementation();
$item = id(new PHUIObjectItemView())
->setHeader($blueprint->getBlueprintName())
->setHref($blueprint->getURI())
->setObjectName(pht('Blueprint %d', $blueprint->getID()));
if (!$impl->isEnabled()) {
$item->setDisabled(true);
$item->addIcon('fa-chain-broken grey', pht('Implementation'));
}
if ($blueprint->getIsDisabled()) {
$item->setDisabled(true);
$item->addIcon('fa-ban grey', pht('Disabled'));
}
$impl_icon = $impl->getBlueprintIcon();
$impl_name = $impl->getBlueprintName();
$impl_icon = id(new PHUIIconView())
->setIcon($impl_icon, 'lightgreytext');
$item->addAttribute(array($impl_icon, ' ', $impl_name));
$phid = $blueprint->getPHID();
$project_phids = $edge_query->getDestinationPHIDs(array($phid));
if ($project_phids) {
$project_handles = $viewer->loadHandles($project_phids);
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setSlim(true)
->setHandles($project_handles));
}
$view->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($view);
$result->setNoDataString(pht('No blueprints found.'));
return $result;
}
}
diff --git a/src/applications/drydock/query/DrydockLeaseSearchEngine.php b/src/applications/drydock/query/DrydockLeaseSearchEngine.php
index 7e89336fab..95f713c0d4 100644
--- a/src/applications/drydock/query/DrydockLeaseSearchEngine.php
+++ b/src/applications/drydock/query/DrydockLeaseSearchEngine.php
@@ -1,123 +1,123 @@
<?php
final class DrydockLeaseSearchEngine
extends PhabricatorApplicationSearchEngine {
private $resource;
public function setResource($resource) {
$this->resource = $resource;
return $this;
}
public function getResource() {
return $this->resource;
}
public function getResultTypeDescription() {
return pht('Drydock Leases');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function newQuery() {
$query = new DrydockLeaseQuery();
$resource = $this->getResource();
if ($resource) {
$query->withResourcePHIDs(array($resource->getPHID()));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['ownerPHIDs']) {
$query->withOwnerPHIDs($map['ownerPHIDs']);
}
if ($map['resourcePHIDs']) {
$query->withResourcePHIDs($map['resourcePHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setOptions(DrydockLeaseStatus::getStatusMap()),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Owners'))
->setKey('ownerPHIDs')
->setAliases(array('owner', 'owners', 'ownerPHID'))
->setDescription(pht('Search leases by owner.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Resources'))
->setKey('resourcePHIDs')
->setAliases(array('resorucePHID', 'resource', 'resources'))
->setDescription(pht('Search leases by resource.')),
);
}
protected function getURI($path) {
$resource = $this->getResource();
if ($resource) {
$id = $resource->getID();
return "/drydock/resource/{$id}/leases/".$path;
} else {
return '/drydock/lease/'.$path;
}
}
protected function getBuiltinQueryNames() {
return array(
'active' => pht('Active Leases'),
'all' => pht('All Leases'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter(
'statuses',
array(
DrydockLeaseStatus::STATUS_PENDING,
DrydockLeaseStatus::STATUS_ACQUIRED,
DrydockLeaseStatus::STATUS_ACTIVE,
));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $leases,
PhabricatorSavedQuery $saved,
array $handles) {
$list = id(new DrydockLeaseListView())
->setUser($this->requireViewer())
->setLeases($leases);
return id(new PhabricatorApplicationSearchResultView())
->setContent($list);
}
}
diff --git a/src/applications/drydock/query/DrydockLogSearchEngine.php b/src/applications/drydock/query/DrydockLogSearchEngine.php
index 3602714a60..553f4be486 100644
--- a/src/applications/drydock/query/DrydockLogSearchEngine.php
+++ b/src/applications/drydock/query/DrydockLogSearchEngine.php
@@ -1,159 +1,159 @@
<?php
final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine {
private $blueprint;
private $resource;
private $lease;
private $operation;
public function setBlueprint(DrydockBlueprint $blueprint) {
$this->blueprint = $blueprint;
return $this;
}
public function getBlueprint() {
return $this->blueprint;
}
public function setResource(DrydockResource $resource) {
$this->resource = $resource;
return $this;
}
public function getResource() {
return $this->resource;
}
public function setLease(DrydockLease $lease) {
$this->lease = $lease;
return $this;
}
public function getLease() {
return $this->lease;
}
public function setOperation(DrydockRepositoryOperation $operation) {
$this->operation = $operation;
return $this;
}
public function getOperation() {
return $this->operation;
}
public function canUseInPanelContext() {
// Prevent use on Dashboard panels since all log queries currently need a
// parent object and these don't seem particularly useful in any case.
return false;
}
public function getResultTypeDescription() {
return pht('Drydock Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function newQuery() {
$query = new DrydockLogQuery();
$blueprint = $this->getBlueprint();
if ($blueprint) {
$query->withBlueprintPHIDs(array($blueprint->getPHID()));
}
$resource = $this->getResource();
if ($resource) {
$query->withResourcePHIDs(array($resource->getPHID()));
}
$lease = $this->getLease();
if ($lease) {
$query->withLeasePHIDs(array($lease->getPHID()));
}
$operation = $this->getOperation();
if ($operation) {
$query->withOperationPHIDs(array($operation->getPHID()));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getURI($path) {
$blueprint = $this->getBlueprint();
if ($blueprint) {
$id = $blueprint->getID();
return "/drydock/blueprint/{$id}/logs/{$path}";
}
$resource = $this->getResource();
if ($resource) {
$id = $resource->getID();
return "/drydock/resource/{$id}/logs/{$path}";
}
$lease = $this->getLease();
if ($lease) {
$id = $lease->getID();
return "/drydock/lease/{$id}/logs/{$path}";
}
$operation = $this->getOperation();
if ($operation) {
$id = $operation->getID();
return "/drydock/operation/{$id}/logs/{$path}";
}
throw new Exception(
pht(
'Search engine has no blueprint, resource, lease, or operation.'));
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Logs'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
$list = id(new DrydockLogListView())
->setUser($this->requireViewer())
->setLogs($logs);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($list);
return $result;
}
}
diff --git a/src/applications/drydock/query/DrydockQuery.php b/src/applications/drydock/query/DrydockQuery.php
index 4f3f768d37..3db247b581 100644
--- a/src/applications/drydock/query/DrydockQuery.php
+++ b/src/applications/drydock/query/DrydockQuery.php
@@ -1,9 +1,9 @@
<?php
abstract class DrydockQuery extends PhabricatorCursorPagedPolicyAwareQuery {
public function getQueryApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
}
diff --git a/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php b/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php
index eeb85329bf..3ab573dd8f 100644
--- a/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php
+++ b/src/applications/drydock/query/DrydockRepositoryOperationSearchEngine.php
@@ -1,135 +1,135 @@
<?php
final class DrydockRepositoryOperationSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Drydock Repository Operations');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function newQuery() {
return id(new DrydockRepositoryOperationQuery());
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['states']) {
$query->withOperationStates($map['states']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setDatasource(new DiffusionRepositoryFunctionDatasource()),
// NOTE: Repository operations aren't necessarily created by a real
// user, but for now they normally are. Just use a user typeahead until
// more use cases arise.
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors', 'authorPHID')),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('States'))
->setKey('states')
->setAliases(array('state'))
->setOptions(DrydockRepositoryOperation::getOperationStateNameMap()),
);
}
protected function getURI($path) {
return '/drydock/operation/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Operations'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $operations,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($operations, 'DrydockRepositoryOperation');
$viewer = $this->requireViewer();
$view = new PHUIObjectItemListView();
foreach ($operations as $operation) {
$id = $operation->getID();
$item = id(new PHUIObjectItemView())
->setHeader($operation->getOperationDescription($viewer))
->setHref($this->getApplicationURI("operation/{$id}/"))
->setObjectName(pht('Repository Operation %d', $id));
$state = $operation->getOperationState();
$icon = DrydockRepositoryOperation::getOperationStateIcon($state);
$name = DrydockRepositoryOperation::getOperationStateName($state);
$item->setStatusIcon($icon, $name);
$created = phabricator_datetime($operation->getDateCreated(), $viewer);
$item->addIcon(null, $created);
$item->addByline(
array(
pht('Via:'),
' ',
$viewer->renderHandle($operation->getAuthorPHID()),
));
$object_phid = $operation->getObjectPHID();
$repository_phid = $operation->getRepositoryPHID();
$item->addAttribute($viewer->renderHandle($object_phid));
if ($repository_phid !== $object_phid) {
$item->addAttribute($viewer->renderHandle($repository_phid));
}
$view->addItem($item);
}
$result = id(new PhabricatorApplicationSearchResultView())
->setObjectList($view)
->setNoDataString(pht('No matching operations.'));
return $result;
}
}
diff --git a/src/applications/drydock/query/DrydockResourceSearchEngine.php b/src/applications/drydock/query/DrydockResourceSearchEngine.php
index 9015f92408..d3fed0fd78 100644
--- a/src/applications/drydock/query/DrydockResourceSearchEngine.php
+++ b/src/applications/drydock/query/DrydockResourceSearchEngine.php
@@ -1,116 +1,116 @@
<?php
final class DrydockResourceSearchEngine
extends PhabricatorApplicationSearchEngine {
private $blueprint;
public function setBlueprint(DrydockBlueprint $blueprint) {
$this->blueprint = $blueprint;
return $this;
}
public function getBlueprint() {
return $this->blueprint;
}
public function getResultTypeDescription() {
return pht('Drydock Resources');
}
public function getApplicationClassName() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function newQuery() {
$query = new DrydockResourceQuery();
$blueprint = $this->getBlueprint();
if ($blueprint) {
$query->withBlueprintPHIDs(array($blueprint->getPHID()));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['blueprintPHIDs']) {
$query->withBlueprintPHIDs($map['blueprintPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setOptions(DrydockResourceStatus::getStatusMap()),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Blueprints'))
->setKey('blueprintPHIDs')
->setAliases(array('blueprintPHID', 'blueprints', 'blueprint'))
->setDescription(
pht('Search for resources generated by particular blueprints.')),
);
}
protected function getURI($path) {
$blueprint = $this->getBlueprint();
if ($blueprint) {
$id = $blueprint->getID();
return "/drydock/blueprint/{$id}/resources/".$path;
} else {
return '/drydock/resource/'.$path;
}
}
protected function getBuiltinQueryNames() {
return array(
'active' => pht('Active Resources'),
'all' => pht('All Resources'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter(
'statuses',
array(
DrydockResourceStatus::STATUS_PENDING,
DrydockResourceStatus::STATUS_ACTIVE,
));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $resources,
PhabricatorSavedQuery $query,
array $handles) {
$list = id(new DrydockResourceListView())
->setUser($this->requireViewer())
->setResources($resources);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($list);
return $result;
}
}
diff --git a/src/applications/drydock/typeahead/DrydockBlueprintDatasource.php b/src/applications/drydock/typeahead/DrydockBlueprintDatasource.php
index d36a2bc64b..7cdade856c 100644
--- a/src/applications/drydock/typeahead/DrydockBlueprintDatasource.php
+++ b/src/applications/drydock/typeahead/DrydockBlueprintDatasource.php
@@ -1,52 +1,52 @@
<?php
final class DrydockBlueprintDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a blueprint name...');
}
public function getBrowseTitle() {
return pht('Browse Blueprints');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$blueprints = id(new DrydockBlueprintQuery())
->setViewer($viewer)
->withDatasourceQuery($raw_query)
->execute();
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($blueprints, 'getPHID'))
->execute();
$results = array();
foreach ($blueprints as $blueprint) {
$handle = $handles[$blueprint->getPHID()];
$result = id(new PhabricatorTypeaheadResult())
->setName($handle->getFullName())
->setPHID($handle->getPHID());
if ($blueprint->getIsDisabled()) {
$result->setClosed(pht('Disabled'));
}
$result->addAttribute(
$blueprint->getImplementation()->getBlueprintName());
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/drydock/typeahead/DrydockLeaseDatasource.php b/src/applications/drydock/typeahead/DrydockLeaseDatasource.php
index feb6bd9368..d21f99393e 100644
--- a/src/applications/drydock/typeahead/DrydockLeaseDatasource.php
+++ b/src/applications/drydock/typeahead/DrydockLeaseDatasource.php
@@ -1,36 +1,36 @@
<?php
final class DrydockLeaseDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a lease ID (exact match)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$leases = id(new DrydockLeaseQuery())
->setViewer($viewer)
->withDatasourceQuery($raw_query)
->execute();
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($leases, 'getPHID'))
->execute();
$results = array();
foreach ($handles as $handle) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
->setPHID($handle->getPHID());
}
return $results;
}
}
diff --git a/src/applications/drydock/typeahead/DrydockResourceDatasource.php b/src/applications/drydock/typeahead/DrydockResourceDatasource.php
index 6e0b8f7116..b8fc292b5e 100644
--- a/src/applications/drydock/typeahead/DrydockResourceDatasource.php
+++ b/src/applications/drydock/typeahead/DrydockResourceDatasource.php
@@ -1,36 +1,36 @@
<?php
final class DrydockResourceDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a resource name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorDrydockApplication';
+ return PhabricatorDrydockApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$resources = id(new DrydockResourceQuery())
->setViewer($viewer)
->withDatasourceQuery($raw_query)
->execute();
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($resources, 'getPHID'))
->execute();
$results = array();
foreach ($handles as $handle) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
->setPHID($handle->getPHID());
}
return $results;
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedQuery.php b/src/applications/feed/query/PhabricatorFeedQuery.php
index 8302af20c1..51d0d1544a 100644
--- a/src/applications/feed/query/PhabricatorFeedQuery.php
+++ b/src/applications/feed/query/PhabricatorFeedQuery.php
@@ -1,175 +1,175 @@
<?php
final class PhabricatorFeedQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $filterPHIDs;
private $chronologicalKeys;
private $rangeMin;
private $rangeMax;
public function withFilterPHIDs(array $phids) {
$this->filterPHIDs = $phids;
return $this;
}
public function withChronologicalKeys(array $keys) {
$this->chronologicalKeys = $keys;
return $this;
}
public function withEpochInRange($range_min, $range_max) {
$this->rangeMin = $range_min;
$this->rangeMax = $range_max;
return $this;
}
public function newResultObject() {
return new PhabricatorFeedStoryData();
}
protected function loadPage() {
// NOTE: We return raw rows from this method, which is a little unusual.
return $this->loadStandardPageRows($this->newResultObject());
}
protected function willFilterPage(array $data) {
$stories = PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer());
foreach ($stories as $key => $story) {
if (!$story->isVisibleInFeed()) {
unset($stories[$key]);
}
}
return $stories;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
// NOTE: We perform this join unconditionally (even if we have no filter
// PHIDs) to omit rows which have no story references. These story data
// rows are notifications or realtime alerts.
$ref_table = new PhabricatorFeedStoryReference();
$joins[] = qsprintf(
$conn,
'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey',
$ref_table->getTableName());
return $joins;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->filterPHIDs !== null) {
$where[] = qsprintf(
$conn,
'ref.objectPHID IN (%Ls)',
$this->filterPHIDs);
}
if ($this->chronologicalKeys !== null) {
// NOTE: We can't use "%d" to format these large integers on 32-bit
// systems. Historically, we formatted these into integers in an
// awkward way because MySQL could sometimes (?) fail to use the proper
// keys if the values were formatted as strings instead of integers.
// After the "qsprintf()" update to use PhutilQueryString, we can no
// longer do this in a sneaky way. However, the MySQL key issue also
// no longer appears to reproduce across several systems. So: just use
// strings until problems turn up?
$where[] = qsprintf(
$conn,
'ref.chronologicalKey IN (%Ls)',
$this->chronologicalKeys);
}
// NOTE: We may not have 64-bit PHP, so do the shifts in MySQL instead.
// From EXPLAIN, it appears like MySQL is smart enough to compute the
// result and make use of keys to execute the query.
if ($this->rangeMin !== null) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey >= (%d << 32)',
$this->rangeMin);
}
if ($this->rangeMax !== null) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey < (%d << 32)',
$this->rangeMax);
}
return $where;
}
protected function buildGroupClause(AphrontDatabaseConnection $conn) {
if ($this->filterPHIDs !== null) {
return qsprintf($conn, 'GROUP BY ref.chronologicalKey');
} else {
return qsprintf($conn, 'GROUP BY story.chronologicalKey');
}
}
protected function getDefaultOrderVector() {
return array('key');
}
public function getBuiltinOrders() {
return array(
'newest' => array(
'vector' => array('key'),
'name' => pht('Creation (Newest First)'),
'aliases' => array('created'),
),
'oldest' => array(
'vector' => array('-key'),
'name' => pht('Creation (Oldest First)'),
),
);
}
public function getOrderableColumns() {
$table = ($this->filterPHIDs ? 'ref' : 'story');
return array(
'key' => array(
'table' => $table,
'column' => 'chronologicalKey',
'type' => 'string',
'unique' => true,
),
);
}
protected function applyExternalCursorConstraintsToQuery(
PhabricatorCursorPagedPolicyAwareQuery $subquery,
$cursor) {
$subquery->withChronologicalKeys(array($cursor));
}
protected function newExternalCursorStringForResult($object) {
return $object->getChronologicalKey();
}
protected function newPagingMapFromPartialObject($object) {
// This query is unusual, and the "object" is a raw result row.
return array(
'key' => $object['chronologicalKey'],
);
}
protected function getPrimaryTableAlias() {
return 'story';
}
public function getQueryApplicationClass() {
- return 'PhabricatorFeedApplication';
+ return PhabricatorFeedApplication::class;
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedSearchEngine.php b/src/applications/feed/query/PhabricatorFeedSearchEngine.php
index d17c756524..58a00deda2 100644
--- a/src/applications/feed/query/PhabricatorFeedSearchEngine.php
+++ b/src/applications/feed/query/PhabricatorFeedSearchEngine.php
@@ -1,162 +1,162 @@
<?php
final class PhabricatorFeedSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Feed Stories');
}
public function getApplicationClassName() {
- return 'PhabricatorFeedApplication';
+ return PhabricatorFeedApplication::class;
}
public function newQuery() {
return new PhabricatorFeedQuery();
}
protected function shouldShowOrderField() {
return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Include Users'))
->setKey('userPHIDs'),
// NOTE: This query is not executed with EdgeLogic, so we can't use
// a fancy logical datasource.
id(new PhabricatorSearchDatasourceField())
->setDatasource(new PhabricatorProjectDatasource())
->setLabel(pht('Include Projects'))
->setKey('projectPHIDs'),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs After'))
->setKey('rangeStart'),
id(new PhabricatorSearchDateControlField())
->setLabel(pht('Occurs Before'))
->setKey('rangeEnd'),
// NOTE: This is a legacy field retained only for backward
// compatibility. If the projects field used EdgeLogic, we could use
// `viewerprojects()` to execute an equivalent query.
id(new PhabricatorSearchCheckboxesField())
->setKey('viewerProjects')
->setOptions(
array(
'self' => pht('Include stories about projects I am a member of.'),
)),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$phids = array();
if ($map['userPHIDs']) {
$phids += array_fuse($map['userPHIDs']);
}
if ($map['projectPHIDs']) {
$phids += array_fuse($map['projectPHIDs']);
}
// NOTE: This value may be `true` for older saved queries, or
// `array('self')` for newer ones.
$viewer_projects = $map['viewerProjects'];
if ($viewer_projects) {
$viewer = $this->requireViewer();
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs(array($viewer->getPHID()))
->execute();
$phids += array_fuse(mpull($projects, 'getPHID'));
}
if ($phids) {
$query->withFilterPHIDs($phids);
}
$range_min = $map['rangeStart'];
if ($range_min) {
$range_min = $range_min->getEpoch();
}
$range_max = $map['rangeEnd'];
if ($range_max) {
$range_max = $range_max->getEpoch();
}
if ($range_min && $range_max) {
if ($range_min > $range_max) {
throw new PhabricatorSearchConstraintException(
pht(
'The specified "Occurs Before" date is earlier in time than the '.
'specified "Occurs After" date, so this query can never match '.
'any results.'));
}
}
if ($range_min || $range_max) {
$query->withEpochInRange($range_min, $range_max);
}
return $query;
}
protected function getURI($path) {
return '/feed/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Stories'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['projects'] = pht('Tags');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'projects':
return $query->setParameter('viewerProjects', array('self'));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $objects,
PhabricatorSavedQuery $query,
array $handles) {
$builder = new PhabricatorFeedBuilder($objects);
if ($this->isPanelContext()) {
$builder->setShowHovercards(false);
} else {
$builder->setShowHovercards(true);
}
$builder->setUser($this->requireViewer());
$view = $builder->buildView();
$list = phutil_tag_div('phabricator-feed-frame', $view);
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($list);
return $result;
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedTransactionQuery.php b/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
index d0a9f53e35..93e90e2ef7 100644
--- a/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
+++ b/src/applications/feed/query/PhabricatorFeedTransactionQuery.php
@@ -1,215 +1,215 @@
<?php
final class PhabricatorFeedTransactionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $authorPHIDs;
private $objectTypes;
private $createdMin;
private $createdMax;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withObjectTypes(array $types) {
$this->objectTypes = $types;
return $this;
}
public function withDateCreatedBetween($min, $max) {
$this->createdMin = $min;
$this->createdMax = $max;
return $this;
}
public function newResultObject() {
// Return an arbitrary valid transaction object. The actual query may
// return objects of any subclass of "ApplicationTransaction" when it is
// executed, but we need to pick something concrete here to make some
// integrations work (like automatic handling of PHIDs in data export).
return new PhabricatorUserTransaction();
}
protected function loadPage() {
$queries = $this->newTransactionQueries();
$xactions = array();
if ($this->shouldLimitResults()) {
$limit = $this->getRawResultLimit();
if (!$limit) {
$limit = null;
}
} else {
$limit = null;
}
// We're doing a bit of manual work to get paging working, because this
// query aggregates the results of a large number of subqueries.
// Overall, we're ordering transactions by "<dateCreated, phid>". Ordering
// by PHID is not very meaningful, but we don't need the ordering to be
// especially meaningful, just consistent. Using PHIDs is easy and does
// everything we need it to technically.
// To actually configure paging, if we have an external cursor, we load
// the internal cursor first. Then we pass it to each subquery and the
// subqueries pretend they just loaded a page where it was the last object.
// This configures their queries properly and we can aggregate a cohesive
// set of results by combining all the queries.
$cursor = $this->getExternalCursorString();
if ($cursor !== null) {
$cursor_object = $this->newInternalCursorFromExternalCursor($cursor);
} else {
$cursor_object = null;
}
$is_reversed = $this->getIsQueryOrderReversed();
$created_min = $this->createdMin;
$created_max = $this->createdMax;
$xaction_phids = $this->phids;
$author_phids = $this->authorPHIDs;
foreach ($queries as $query) {
$query->withDateCreatedBetween($created_min, $created_max);
if ($xaction_phids !== null) {
$query->withPHIDs($xaction_phids);
}
if ($author_phids !== null) {
$query->withAuthorPHIDs($author_phids);
}
if ($limit !== null) {
$query->setLimit($limit);
}
if ($cursor_object !== null) {
$query
->setAggregatePagingCursor($cursor_object)
->setIsQueryOrderReversed($is_reversed);
}
$query->setOrder('global');
$query_xactions = $query->execute();
foreach ($query_xactions as $query_xaction) {
$xactions[] = $query_xaction;
}
$xactions = msortv($xactions, 'newGlobalSortVector');
if ($is_reversed) {
$xactions = array_reverse($xactions);
}
if ($limit !== null) {
$xactions = array_slice($xactions, 0, $limit);
// If we've found enough transactions to fill up the entire requested
// page size, we can narrow the search window: transactions after the
// last transaction we've found so far can't possibly be part of the
// result set.
if (count($xactions) === $limit) {
$last_date = last($xactions)->getDateCreated();
if ($is_reversed) {
if ($created_max === null) {
$created_max = $last_date;
} else {
$created_max = min($created_max, $last_date);
}
} else {
if ($created_min === null) {
$created_min = $last_date;
} else {
$created_min = max($created_min, $last_date);
}
}
}
}
}
return $xactions;
}
public function getQueryApplicationClass() {
- return 'PhabricatorFeedApplication';
+ return PhabricatorFeedApplication::class;
}
private function newTransactionQueries() {
$viewer = $this->getViewer();
$queries = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationTransactionQuery')
->execute();
$type_map = array();
// If we're querying for specific transaction PHIDs, we only need to
// consider queries which may load transactions with subtypes present
// in the list.
// For example, if we're loading Maniphest Task transaction PHIDs, we know
// we only have to look at Maniphest Task transactions, since other types
// of objects will never have the right transaction PHIDs.
$xaction_phids = $this->phids;
if ($xaction_phids) {
foreach ($xaction_phids as $xaction_phid) {
$type_map[phid_get_subtype($xaction_phid)] = true;
}
}
$object_types = $this->objectTypes;
if ($object_types) {
$object_types = array_fuse($object_types);
}
$results = array();
foreach ($queries as $query) {
$query_type = $query->getTemplateApplicationTransaction()
->getApplicationTransactionType();
if ($type_map) {
if (!isset($type_map[$query_type])) {
continue;
}
}
if ($object_types) {
if (!isset($object_types[$query_type])) {
continue;
}
}
$results[] = id(clone $query)
->setViewer($viewer)
->setParentQuery($this);
}
return $results;
}
protected function newExternalCursorStringForResult($object) {
return (string)$object->getPHID();
}
protected function applyExternalCursorConstraintsToQuery(
PhabricatorCursorPagedPolicyAwareQuery $subquery,
$cursor) {
$subquery->withPHIDs(array($cursor));
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php b/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
index 0cbbcd23b1..cc04532d56 100644
--- a/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
+++ b/src/applications/feed/query/PhabricatorFeedTransactionSearchEngine.php
@@ -1,230 +1,230 @@
<?php
final class PhabricatorFeedTransactionSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Transactions');
}
public function getApplicationClassName() {
- return 'PhabricatorFeedApplication';
+ return PhabricatorFeedApplication::class;
}
public function newQuery() {
return new PhabricatorFeedTransactionQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Object Types'))
->setKey('objectTypes')
->setAliases(array('objectType'))
->setDatasource(new PhabricatorTransactionsObjectTypeDatasource()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['objectTypes']) {
$query->withObjectTypes($map['objectTypes']);
}
$created_min = $map['createdStart'];
$created_max = $map['createdEnd'];
if ($created_min && $created_max) {
if ($created_min > $created_max) {
throw new PhabricatorSearchConstraintException(
pht(
'The specified "Created Before" date is earlier in time than the '.
'specified "Created After" date, so this query can never match '.
'any results.'));
}
}
if ($created_min || $created_max) {
$query->withDateCreatedBetween($created_min, $created_max);
}
return $query;
}
protected function getURI($path) {
return '/feed/transactions/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Transactions'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery()
->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $objects,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($objects, 'PhabricatorApplicationTransaction');
$viewer = $this->requireViewer();
$handle_phids = array();
foreach ($objects as $object) {
$author_phid = $object->getAuthorPHID();
if ($author_phid !== null) {
$handle_phids[] = $author_phid;
}
$object_phid = $object->getObjectPHID();
if ($object_phid !== null) {
$handle_phids[] = $object_phid;
}
}
$handles = $viewer->loadHandles($handle_phids);
$rows = array();
foreach ($objects as $object) {
$author_phid = $object->getAuthorPHID();
$object_phid = $object->getObjectPHID();
try {
$title = $object->getTitle();
} catch (Exception $ex) {
$title = null;
}
$rows[] = array(
$handles[$author_phid]->renderLink(),
$handles[$object_phid]->renderLink(),
AphrontTableView::renderSingleDisplayLine($title),
phabricator_datetime($object->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setHeaders(
array(
pht('Author'),
pht('Object'),
pht('Transaction'),
pht('Date'),
))
->setColumnClasses(
array(
null,
null,
'wide',
'right',
));
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
protected function newExportFields() {
$fields = array(
id(new PhabricatorPHIDExportField())
->setKey('authorPHID')
->setLabel(pht('Author PHID')),
id(new PhabricatorStringExportField())
->setKey('author')
->setLabel(pht('Author')),
id(new PhabricatorStringExportField())
->setKey('objectType')
->setLabel(pht('Object Type')),
id(new PhabricatorPHIDExportField())
->setKey('objectPHID')
->setLabel(pht('Object PHID')),
id(new PhabricatorStringExportField())
->setKey('objectName')
->setLabel(pht('Object Name')),
id(new PhabricatorStringExportField())
->setKey('description')
->setLabel(pht('Description')),
);
return $fields;
}
protected function newExportData(array $xactions) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($xactions as $xaction) {
$phids[] = $xaction->getAuthorPHID();
$phids[] = $xaction->getObjectPHID();
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($xactions as $xaction) {
$xaction_phid = $xaction->getPHID();
$author_phid = $xaction->getAuthorPHID();
if ($author_phid) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = null;
}
$object_phid = $xaction->getObjectPHID();
if ($object_phid) {
$object_name = $handles[$object_phid]->getName();
} else {
$object_name = null;
}
$old_target = $xaction->getRenderingTarget();
try {
$description = $xaction
->setRenderingTarget(PhabricatorApplicationTransaction::TARGET_TEXT)
->getTitle();
} catch (Exception $ex) {
$description = null;
}
$xaction->setRenderingTarget($old_target);
$export[] = array(
'authorPHID' => $author_phid,
'author' => $author_name,
'objectType' => phid_get_subtype($xaction_phid),
'objectPHID' => $object_phid,
'objectName' => $object_name,
'description' => $description,
);
}
return $export;
}
}
diff --git a/src/applications/files/editor/PhabricatorFileEditEngine.php b/src/applications/files/editor/PhabricatorFileEditEngine.php
index a6a39852cb..c5ff926418 100644
--- a/src/applications/files/editor/PhabricatorFileEditEngine.php
+++ b/src/applications/files/editor/PhabricatorFileEditEngine.php
@@ -1,89 +1,89 @@
<?php
final class PhabricatorFileEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'files.file';
public function getEngineName() {
return pht('Files');
}
protected function supportsEditEngineConfiguration() {
return false;
}
protected function getCreateNewObjectPolicy() {
// TODO: For now, this EditEngine can only edit objects, since there is
// a lot of complexity in dealing with file data during file creation.
return PhabricatorPolicies::POLICY_NOONE;
}
public function getSummaryHeader() {
return pht('Configure Files Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Files.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
protected function newEditableObject() {
return PhabricatorFile::initializeNewFile();
}
protected function newObjectQuery() {
$query = new PhabricatorFileQuery();
$query->withIsDeleted(false);
return $query;
}
protected function getObjectCreateTitleText($object) {
return pht('Create New File');
}
protected function getObjectEditTitleText($object) {
return pht('Edit File: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
protected function getObjectCreateShortText() {
return pht('Create File');
}
protected function getObjectName() {
return pht('File');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setTransactionType(PhabricatorFileNameTransaction::TRANSACTIONTYPE)
->setDescription(pht('The name of the file.'))
->setConduitDescription(pht('Rename the file.'))
->setConduitTypeDescription(pht('New file name.'))
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('alt')
->setLabel(pht('Alt Text'))
->setTransactionType(PhabricatorFileAltTextTransaction::TRANSACTIONTYPE)
->setDescription(pht('Human-readable file description.'))
->setConduitDescription(pht('Set the file alt text.'))
->setConduitTypeDescription(pht('New alt text.'))
->setValue($object->getCustomAltText()),
);
}
}
diff --git a/src/applications/files/editor/PhabricatorFileEditor.php b/src/applications/files/editor/PhabricatorFileEditor.php
index 91d168e68d..8892f80174 100644
--- a/src/applications/files/editor/PhabricatorFileEditor.php
+++ b/src/applications/files/editor/PhabricatorFileEditor.php
@@ -1,76 +1,76 @@
<?php
final class PhabricatorFileEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Files');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[File]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new FileReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject("F{$id}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addTextSection(
pht('FILE DETAIL'),
PhabricatorEnv::getProductionURI($object->getInfoURI()));
return $body;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/files/phid/PhabricatorFileFilePHIDType.php b/src/applications/files/phid/PhabricatorFileFilePHIDType.php
index c583595c4d..70a58834c4 100644
--- a/src/applications/files/phid/PhabricatorFileFilePHIDType.php
+++ b/src/applications/files/phid/PhabricatorFileFilePHIDType.php
@@ -1,77 +1,77 @@
<?php
final class PhabricatorFileFilePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'FILE';
public function getTypeName() {
return pht('File');
}
public function newObject() {
return new PhabricatorFile();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorFileQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$file = $objects[$phid];
$id = $file->getID();
$name = $file->getName();
$uri = $file->getInfoURI();
$handle->setName("F{$id}");
$handle->setFullName("F{$id}: {$name}");
$handle->setURI($uri);
$icon = FileTypeIcon::getFileIcon($name);
$handle->setIcon($icon);
}
}
public function canLoadNamedObject($name) {
return preg_match('/^F\d*[1-9]\d*$/', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorFileQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/files/query/PhabricatorFileAttachmentQuery.php b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
index 5fb37dc32e..50aea1a839 100644
--- a/src/applications/files/query/PhabricatorFileAttachmentQuery.php
+++ b/src/applications/files/query/PhabricatorFileAttachmentQuery.php
@@ -1,131 +1,131 @@
<?php
final class PhabricatorFileAttachmentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $objectPHIDs;
private $filePHIDs;
private $needFiles;
private $visibleFiles;
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withFilePHIDs(array $file_phids) {
$this->filePHIDs = $file_phids;
return $this;
}
public function withVisibleFiles($visible_files) {
$this->visibleFiles = $visible_files;
return $this;
}
public function needFiles($need) {
$this->needFiles = $need;
return $this;
}
public function newResultObject() {
return new PhabricatorFileAttachment();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'attachments.objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->filePHIDs !== null) {
$where[] = qsprintf(
$conn,
'attachments.filePHID IN (%Ls)',
$this->filePHIDs);
}
return $where;
}
protected function willFilterPage(array $attachments) {
$viewer = $this->getViewer();
$object_phids = array();
foreach ($attachments as $attachment) {
$object_phid = $attachment->getObjectPHID();
$object_phids[$object_phid] = $object_phid;
}
if ($object_phids) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
foreach ($attachments as $key => $attachment) {
$object_phid = $attachment->getObjectPHID();
$object = idx($objects, $object_phid);
if (!$object) {
$this->didRejectResult($attachment);
unset($attachments[$key]);
continue;
}
$attachment->attachObject($object);
}
if ($this->needFiles) {
$file_phids = array();
foreach ($attachments as $attachment) {
$file_phid = $attachment->getFilePHID();
$file_phids[$file_phid] = $file_phid;
}
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->setParentQuery($this)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($attachments as $key => $attachment) {
$file_phid = $attachment->getFilePHID();
$file = idx($files, $file_phid);
if ($this->visibleFiles && !$file) {
$this->didRejectResult($attachment);
unset($attachments[$key]);
continue;
}
$attachment->attachFile($file);
}
}
return $attachments;
}
protected function getPrimaryTableAlias() {
return 'attachments';
}
public function getQueryApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
}
diff --git a/src/applications/files/query/PhabricatorFileChunkQuery.php b/src/applications/files/query/PhabricatorFileChunkQuery.php
index 4398860569..f2c104dc7a 100644
--- a/src/applications/files/query/PhabricatorFileChunkQuery.php
+++ b/src/applications/files/query/PhabricatorFileChunkQuery.php
@@ -1,134 +1,134 @@
<?php
final class PhabricatorFileChunkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $chunkHandles;
private $rangeStart;
private $rangeEnd;
private $isComplete;
private $needDataFiles;
public function withChunkHandles(array $handles) {
$this->chunkHandles = $handles;
return $this;
}
public function withByteRange($start, $end) {
$this->rangeStart = $start;
$this->rangeEnd = $end;
return $this;
}
public function withIsComplete($complete) {
$this->isComplete = $complete;
return $this;
}
public function needDataFiles($need) {
$this->needDataFiles = $need;
return $this;
}
protected function loadPage() {
$table = new PhabricatorFileChunk();
$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 willFilterPage(array $chunks) {
if ($this->needDataFiles) {
$file_phids = mpull($chunks, 'getDataFilePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($chunks as $key => $chunk) {
$data_phid = $chunk->getDataFilePHID();
if (!$data_phid) {
$chunk->attachDataFile(null);
continue;
}
$file = idx($files, $data_phid);
if (!$file) {
unset($chunks[$key]);
$this->didRejectResult($chunk);
continue;
}
$chunk->attachDataFile($file);
}
if (!$chunks) {
return $chunks;
}
}
return $chunks;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->chunkHandles !== null) {
$where[] = qsprintf(
$conn,
'chunkHandle IN (%Ls)',
$this->chunkHandles);
}
if ($this->rangeStart !== null) {
$where[] = qsprintf(
$conn,
'byteEnd > %d',
$this->rangeStart);
}
if ($this->rangeEnd !== null) {
$where[] = qsprintf(
$conn,
'byteStart < %d',
$this->rangeEnd);
}
if ($this->isComplete !== null) {
if ($this->isComplete) {
$where[] = qsprintf(
$conn,
'dataFilePHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'dataFilePHID IS NULL');
}
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
}
diff --git a/src/applications/files/query/PhabricatorFileQuery.php b/src/applications/files/query/PhabricatorFileQuery.php
index 80e511b1e2..e712d533b0 100644
--- a/src/applications/files/query/PhabricatorFileQuery.php
+++ b/src/applications/files/query/PhabricatorFileQuery.php
@@ -1,546 +1,546 @@
<?php
final class PhabricatorFileQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $explicitUploads;
private $transforms;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $contentHashes;
private $minLength;
private $maxLength;
private $names;
private $isPartial;
private $isDeleted;
private $needTransforms;
private $builtinKeys;
private $isBuiltin;
private $storageEngines;
private $attachedObjectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withContentHashes(array $content_hashes) {
$this->contentHashes = $content_hashes;
return $this;
}
public function withBuiltinKeys(array $keys) {
$this->builtinKeys = $keys;
return $this;
}
public function withIsBuiltin($is_builtin) {
$this->isBuiltin = $is_builtin;
return $this;
}
public function withAttachedObjectPHIDs(array $phids) {
$this->attachedObjectPHIDs = $phids;
return $this;
}
/**
* Select files which are transformations of some other file. For example,
* you can use this query to find previously generated thumbnails of an image
* file.
*
* As a parameter, provide a list of transformation specifications. Each
* specification is a dictionary with the keys `originalPHID` and `transform`.
* The `originalPHID` is the PHID of the original file (the file which was
* transformed) and the `transform` is the name of the transform to query
* for. If you pass `true` as the `transform`, all transformations of the
* file will be selected.
*
* For example:
*
* array(
* array(
* 'originalPHID' => 'PHID-FILE-aaaa',
* 'transform' => 'sepia',
* ),
* array(
* 'originalPHID' => 'PHID-FILE-bbbb',
* 'transform' => true,
* ),
* )
*
* This selects the `"sepia"` transformation of the file with PHID
* `PHID-FILE-aaaa` and all transformations of the file with PHID
* `PHID-FILE-bbbb`.
*
* @param list<dict> List of transform specifications, described above.
* @return this
*/
public function withTransforms(array $specs) {
foreach ($specs as $spec) {
if (!is_array($spec) ||
empty($spec['originalPHID']) ||
empty($spec['transform'])) {
throw new Exception(
pht(
"Transform specification must be a dictionary with keys ".
"'%s' and '%s'!",
'originalPHID',
'transform'));
}
}
$this->transforms = $specs;
return $this;
}
public function withLengthBetween($min, $max) {
$this->minLength = $min;
$this->maxLength = $max;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withIsPartial($partial) {
$this->isPartial = $partial;
return $this;
}
public function withIsDeleted($deleted) {
$this->isDeleted = $deleted;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
id(new PhabricatorFileNameNgrams()),
$ngrams);
}
public function withStorageEngines(array $engines) {
$this->storageEngines = $engines;
return $this;
}
public function showOnlyExplicitUploads($explicit_uploads) {
$this->explicitUploads = $explicit_uploads;
return $this;
}
public function needTransforms(array $transforms) {
$this->needTransforms = $transforms;
return $this;
}
public function newResultObject() {
return new PhabricatorFile();
}
protected function loadPage() {
$files = $this->loadStandardPage($this->newResultObject());
if (!$files) {
return $files;
}
// Figure out which files we need to load attached objects for. In most
// cases, we need to load attached objects to perform policy checks for
// files.
// However, in some special cases where we know files will always be
// visible, we skip this. See T8478 and T13106.
$need_objects = array();
$need_xforms = array();
foreach ($files as $file) {
$always_visible = false;
if ($file->getIsProfileImage()) {
$always_visible = true;
}
if ($file->isBuiltin()) {
$always_visible = true;
}
if ($always_visible) {
// We just treat these files as though they aren't attached to
// anything. This saves a query in common cases when we're loading
// profile images or builtins. We could be slightly more nuanced
// about this and distinguish between "not attached to anything" and
// "might be attached but policy checks don't need to care".
$file->attachObjectPHIDs(array());
continue;
}
$need_objects[] = $file;
$need_xforms[] = $file;
}
$viewer = $this->getViewer();
$is_omnipotent = $viewer->isOmnipotent();
// If we have any files left which do need objects, load the edges now.
$object_phids = array();
if ($need_objects) {
$attachments_map = $this->newAttachmentsMap($need_objects);
foreach ($need_objects as $file) {
$file_phid = $file->getPHID();
$phids = $attachments_map[$file_phid];
$file->attachObjectPHIDs($phids);
if ($is_omnipotent) {
// If the viewer is omnipotent, we don't need to load the associated
// objects either since the viewer can certainly see the object.
// Skipping this can improve performance and prevent cycles. This
// could possibly become part of the profile/builtin code above which
// short circuits attacment policy checks in cases where we know them
// to be unnecessary.
continue;
}
foreach ($phids as $phid) {
$object_phids[$phid] = true;
}
}
}
// If this file is a transform of another file, load that file too. If you
// can see the original file, you can see the thumbnail.
// TODO: It might be nice to put this directly on PhabricatorFile and
// remove the PhabricatorTransformedFile table, which would be a little
// simpler.
if ($need_xforms) {
$xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
'transformedPHID IN (%Ls)',
mpull($need_xforms, 'getPHID'));
$xform_phids = mpull($xforms, 'getOriginalPHID', 'getTransformedPHID');
foreach ($xform_phids as $derived_phid => $original_phid) {
$object_phids[$original_phid] = true;
}
} else {
$xform_phids = array();
}
$object_phids = array_keys($object_phids);
// Now, load the objects.
$objects = array();
if ($object_phids) {
// NOTE: We're explicitly turning policy exceptions off, since the rule
// here is "you can see the file if you can see ANY associated object".
// Without this explicit flag, we'll incorrectly throw unless you can
// see ALL associated objects.
$objects = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($object_phids)
->setRaisePolicyExceptions(false)
->execute();
$objects = mpull($objects, null, 'getPHID');
}
foreach ($files as $file) {
$file_objects = array_select_keys($objects, $file->getObjectPHIDs());
$file->attachObjects($file_objects);
}
foreach ($files as $key => $file) {
$original_phid = idx($xform_phids, $file->getPHID());
if ($original_phid == PhabricatorPHIDConstants::PHID_VOID) {
// This is a special case for builtin files, which are handled
// oddly.
$original = null;
} else if ($original_phid) {
$original = idx($objects, $original_phid);
if (!$original) {
// If the viewer can't see the original file, also prevent them from
// seeing the transformed file.
$this->didRejectResult($file);
unset($files[$key]);
continue;
}
} else {
$original = null;
}
$file->attachOriginalFile($original);
}
return $files;
}
private function newAttachmentsMap(array $files) {
$file_phids = mpull($files, 'getPHID');
$attachments_table = new PhabricatorFileAttachment();
$attachments_conn = $attachments_table->establishConnection('r');
$attachments = queryfx_all(
$attachments_conn,
'SELECT filePHID, objectPHID FROM %R WHERE filePHID IN (%Ls)
AND attachmentMode IN (%Ls)',
$attachments_table,
$file_phids,
array(
PhabricatorFileAttachment::MODE_ATTACH,
));
$attachments_map = array_fill_keys($file_phids, array());
foreach ($attachments as $row) {
$file_phid = $row['filePHID'];
$object_phid = $row['objectPHID'];
$attachments_map[$file_phid][] = $object_phid;
}
return $attachments_map;
}
protected function didFilterPage(array $files) {
$xform_keys = $this->needTransforms;
if ($xform_keys !== null) {
$xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
'originalPHID IN (%Ls) AND transform IN (%Ls)',
mpull($files, 'getPHID'),
$xform_keys);
if ($xforms) {
$xfiles = id(new PhabricatorFile())->loadAllWhere(
'phid IN (%Ls)',
mpull($xforms, 'getTransformedPHID'));
$xfiles = mpull($xfiles, null, 'getPHID');
}
$xform_map = array();
foreach ($xforms as $xform) {
$xfile = idx($xfiles, $xform->getTransformedPHID());
if (!$xfile) {
continue;
}
$original_phid = $xform->getOriginalPHID();
$xform_key = $xform->getTransform();
$xform_map[$original_phid][$xform_key] = $xfile;
}
$default_xforms = array_fill_keys($xform_keys, null);
foreach ($files as $file) {
$file_xforms = idx($xform_map, $file->getPHID(), array());
$file_xforms += $default_xforms;
$file->attachTransforms($file_xforms);
}
}
return $files;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->transforms) {
$joins[] = qsprintf(
$conn,
'JOIN %T t ON t.transformedPHID = f.phid',
id(new PhabricatorTransformedFile())->getTableName());
}
if ($this->shouldJoinAttachmentsTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %R attachments ON attachments.filePHID = f.phid
AND attachmentMode IN (%Ls)',
new PhabricatorFileAttachment(),
array(
PhabricatorFileAttachment::MODE_ATTACH,
));
}
return $joins;
}
private function shouldJoinAttachmentsTable() {
return ($this->attachedObjectPHIDs !== null);
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'f.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'f.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'f.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->explicitUploads !== null) {
$where[] = qsprintf(
$conn,
'f.isExplicitUpload = %d',
(int)$this->explicitUploads);
}
if ($this->transforms !== null) {
$clauses = array();
foreach ($this->transforms as $transform) {
if ($transform['transform'] === true) {
$clauses[] = qsprintf(
$conn,
'(t.originalPHID = %s)',
$transform['originalPHID']);
} else {
$clauses[] = qsprintf(
$conn,
'(t.originalPHID = %s AND t.transform = %s)',
$transform['originalPHID'],
$transform['transform']);
}
}
$where[] = qsprintf($conn, '%LO', $clauses);
}
if ($this->dateCreatedAfter !== null) {
$where[] = qsprintf(
$conn,
'f.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore !== null) {
$where[] = qsprintf(
$conn,
'f.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->contentHashes !== null) {
$where[] = qsprintf(
$conn,
'f.contentHash IN (%Ls)',
$this->contentHashes);
}
if ($this->minLength !== null) {
$where[] = qsprintf(
$conn,
'byteSize >= %d',
$this->minLength);
}
if ($this->maxLength !== null) {
$where[] = qsprintf(
$conn,
'byteSize <= %d',
$this->maxLength);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'name in (%Ls)',
$this->names);
}
if ($this->isPartial !== null) {
$where[] = qsprintf(
$conn,
'isPartial = %d',
(int)$this->isPartial);
}
if ($this->isDeleted !== null) {
$where[] = qsprintf(
$conn,
'isDeleted = %d',
(int)$this->isDeleted);
}
if ($this->builtinKeys !== null) {
$where[] = qsprintf(
$conn,
'builtinKey IN (%Ls)',
$this->builtinKeys);
}
if ($this->isBuiltin !== null) {
if ($this->isBuiltin) {
$where[] = qsprintf(
$conn,
'builtinKey IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'builtinKey IS NULL');
}
}
if ($this->storageEngines !== null) {
$where[] = qsprintf(
$conn,
'storageEngine IN (%Ls)',
$this->storageEngines);
}
if ($this->attachedObjectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'attachments.objectPHID IN (%Ls)',
$this->attachedObjectPHIDs);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'f';
}
public function getQueryApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
}
diff --git a/src/applications/files/query/PhabricatorFileSearchEngine.php b/src/applications/files/query/PhabricatorFileSearchEngine.php
index 59810c830c..c2d36acfd6 100644
--- a/src/applications/files/query/PhabricatorFileSearchEngine.php
+++ b/src/applications/files/query/PhabricatorFileSearchEngine.php
@@ -1,214 +1,214 @@
<?php
final class PhabricatorFileSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Files');
}
public function getApplicationClassName() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
$query = new PhabricatorFileQuery();
$query->withIsDeleted(false);
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setKey('authorPHIDs')
->setAliases(array('author', 'authors'))
->setLabel(pht('Authors')),
id(new PhabricatorSearchThreeStateField())
->setKey('explicit')
->setLabel(pht('Upload Source'))
->setOptions(
pht('(Show All)'),
pht('Show Only Manually Uploaded Files'),
pht('Hide Manually Uploaded Files')),
id(new PhabricatorSearchDateField())
->setKey('createdStart')
->setLabel(pht('Created After')),
id(new PhabricatorSearchDateField())
->setKey('createdEnd')
->setLabel(pht('Created Before')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('name')
->setDescription(pht('Search for files by name substring.')),
);
}
protected function getDefaultFieldOrder() {
return array(
'...',
'createdStart',
'createdEnd',
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['explicit'] !== null) {
$query->showOnlyExplicitUploads($map['explicit']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedBefore($map['createdEnd']);
}
if ($map['name'] !== null) {
$query->withNameNgrams($map['name']);
}
return $query;
}
protected function getURI($path) {
return '/file/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
$names += array(
'all' => pht('All'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'authored':
$author_phid = array($this->requireViewer()->getPHID());
return $query
->setParameter('authorPHIDs', $author_phid)
->setParameter('explicit', true);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $files,
PhabricatorSavedQuery $query) {
return mpull($files, 'getAuthorPHID');
}
protected function renderResultList(
array $files,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($files, 'PhabricatorFile');
$request = $this->getRequest();
if ($request) {
$highlighted_ids = $request->getStrList('h');
} else {
$highlighted_ids = array();
}
$viewer = $this->requireViewer();
$highlighted_ids = array_fill_keys($highlighted_ids, true);
$list_view = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($files as $file) {
$id = $file->getID();
$phid = $file->getPHID();
$name = $file->getName();
$file_uri = $this->getApplicationURI("/info/{$phid}/");
$date_created = phabricator_date($file->getDateCreated(), $viewer);
$author_phid = $file->getAuthorPHID();
if ($author_phid) {
$author_link = $handles[$author_phid]->renderLink();
$uploaded = pht('Uploaded by %s on %s', $author_link, $date_created);
} else {
$uploaded = pht('Uploaded on %s', $date_created);
}
$item = id(new PHUIObjectItemView())
->setObject($file)
->setObjectName("F{$id}")
->setHeader($name)
->setHref($file_uri)
->addAttribute($uploaded)
->addIcon('none', phutil_format_bytes($file->getByteSize()));
$ttl = $file->getTTL();
if ($ttl !== null) {
$item->addIcon('blame', pht('Temporary'));
}
if ($file->getIsPartial()) {
$item->addIcon('fa-exclamation-triangle orange', pht('Partial'));
}
if (isset($highlighted_ids[$id])) {
$item->setEffect('highlighted');
}
$list_view->addItem($item);
}
$list_view->appendChild(id(new PhabricatorGlobalUploadTargetView())
->setUser($viewer));
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($list_view);
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Upload a File'))
->setHref('/file/upload/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Just a place for files.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/files/typeahead/PhabricatorIconDatasource.php b/src/applications/files/typeahead/PhabricatorIconDatasource.php
index 63b554a9b7..e904742e26 100644
--- a/src/applications/files/typeahead/PhabricatorIconDatasource.php
+++ b/src/applications/files/typeahead/PhabricatorIconDatasource.php
@@ -1,46 +1,46 @@
<?php
final class PhabricatorIconDatasource extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type an icon name...');
}
public function getBrowseTitle() {
return pht('Browse Icons');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorFilesApplication';
+ return PhabricatorFilesApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$raw_query = $this->getRawQuery();
$icons = id(new PHUIIconView())->getIcons();
$results = array();
foreach ($icons as $icon) {
$display_name = str_replace('fa-', '', $icon);
$result = id(new PhabricatorTypeaheadResult())
->setPHID($icon)
->setName($icon)
->setIcon($icon)
->setDisplayname($display_name)
->addAttribute($icon);
$results[$icon] = $result;
}
return $results;
}
}
diff --git a/src/applications/flag/query/PhabricatorFlagQuery.php b/src/applications/flag/query/PhabricatorFlagQuery.php
index c6c905465d..07b3e09d10 100644
--- a/src/applications/flag/query/PhabricatorFlagQuery.php
+++ b/src/applications/flag/query/PhabricatorFlagQuery.php
@@ -1,179 +1,179 @@
<?php
final class PhabricatorFlagQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const GROUP_COLOR = 'color';
const GROUP_NONE = 'none';
private $ids;
private $ownerPHIDs;
private $types;
private $objectPHIDs;
private $colors;
private $groupBy = self::GROUP_NONE;
private $needHandles;
private $needObjects;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withOwnerPHIDs(array $owner_phids) {
$this->ownerPHIDs = $owner_phids;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withColors(array $colors) {
$this->colors = $colors;
return $this;
}
/**
* NOTE: this is done in PHP and not in MySQL, which means its inappropriate
* for large datasets. Pragmatically, this is fine for user flags which are
* typically well under 100 flags per user.
*/
public function setGroupBy($group) {
$this->groupBy = $group;
return $this;
}
public function needHandles($need) {
$this->needHandles = $need;
return $this;
}
public function needObjects($need) {
$this->needObjects = $need;
return $this;
}
public static function loadUserFlag(PhabricatorUser $user, $object_phid) {
// Specifying the type in the query allows us to use a key.
return id(new PhabricatorFlagQuery())
->setViewer($user)
->withOwnerPHIDs(array($user->getPHID()))
->withTypes(array(phid_get_type($object_phid)))
->withObjectPHIDs(array($object_phid))
->executeOne();
}
protected function loadPage() {
$table = new PhabricatorFlag();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T flag %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $flags) {
if ($this->needObjects) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($flags, 'getObjectPHID'))
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($flags as $key => $flag) {
$object = idx($objects, $flag->getObjectPHID());
if ($object) {
$flags[$key]->attachObject($object);
} else {
unset($flags[$key]);
}
}
}
if ($this->needHandles) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($flags, 'getObjectPHID'))
->execute();
foreach ($flags as $flag) {
$flag->attachHandle($handles[$flag->getObjectPHID()]);
}
}
switch ($this->groupBy) {
case self::GROUP_COLOR:
$flags = msort($flags, 'getColor');
break;
case self::GROUP_NONE:
break;
default:
throw new Exception(
pht('Unknown groupBy parameter: %s', $this->groupBy));
break;
}
return $flags;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'flag.id IN (%Ld)',
$this->ids);
}
if ($this->ownerPHIDs) {
$where[] = qsprintf(
$conn,
'flag.ownerPHID IN (%Ls)',
$this->ownerPHIDs);
}
if ($this->types) {
$where[] = qsprintf(
$conn,
'flag.type IN (%Ls)',
$this->types);
}
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn,
'flag.objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->colors) {
$where[] = qsprintf(
$conn,
'flag.color IN (%Ld)',
$this->colors);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorFlagsApplication';
+ return PhabricatorFlagsApplication::class;
}
}
diff --git a/src/applications/flag/query/PhabricatorFlagSearchEngine.php b/src/applications/flag/query/PhabricatorFlagSearchEngine.php
index a433e4241c..bc571b6bf4 100644
--- a/src/applications/flag/query/PhabricatorFlagSearchEngine.php
+++ b/src/applications/flag/query/PhabricatorFlagSearchEngine.php
@@ -1,194 +1,194 @@
<?php
final class PhabricatorFlagSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Flags');
}
public function getApplicationClassName() {
- return 'PhabricatorFlagsApplication';
+ return PhabricatorFlagsApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('colors', $request->getArr('colors'));
$saved->setParameter('group', $request->getStr('group'));
$saved->setParameter('objectFilter', $request->getStr('objectFilter'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorFlagQuery())
->needHandles(true)
->withOwnerPHIDs(array($this->requireViewer()->getPHID()));
$colors = $saved->getParameter('colors');
if ($colors) {
$query->withColors($colors);
}
$group = $saved->getParameter('group');
$options = $this->getGroupOptions();
if ($group && isset($options[$group])) {
$query->setGroupBy($group);
}
$object_filter = $saved->getParameter('objectFilter');
$objects = $this->getObjectFilterOptions();
if ($object_filter && isset($objects[$object_filter])) {
$query->withTypes(array($object_filter));
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$form
->appendChild(
id(new PhabricatorFlagSelectControl())
->setName('colors')
->setLabel(pht('Colors'))
->setValue($saved_query->getParameter('colors', array())))
->appendChild(
id(new AphrontFormSelectControl())
->setName('group')
->setLabel(pht('Group By'))
->setValue($saved_query->getParameter('group'))
->setOptions($this->getGroupOptions()))
->appendChild(
id(new AphrontFormSelectControl())
->setName('objectFilter')
->setLabel(pht('Object Type'))
->setValue($saved_query->getParameter('objectFilter'))
->setOptions($this->getObjectFilterOptions()));
}
protected function getURI($path) {
return '/flag/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('Flagged'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getGroupOptions() {
return array(
PhabricatorFlagQuery::GROUP_NONE => pht('None'),
PhabricatorFlagQuery::GROUP_COLOR => pht('Color'),
);
}
private function getObjectFilterOptions() {
$objects = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorFlaggableInterface')
->execute();
$all_types = PhabricatorPHIDType::getAllTypes();
$options = array();
foreach ($objects as $object) {
$phid = $object->generatePHID();
$phid_type = phid_get_type($phid);
$type_object = idx($all_types, $phid_type);
if ($type_object) {
$options[$phid_type] = $type_object->getTypeName();
}
}
// sort it alphabetically...
asort($options);
$default_option = array(
0 => pht('All Object Types'),
);
// ...and stick the default option on front
$options = array_merge($default_option, $options);
return $options;
}
protected function renderResultList(
array $flags,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($flags, 'PhabricatorFlag');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($flags as $flag) {
$id = $flag->getID();
$phid = $flag->getObjectPHID();
$class = PhabricatorFlagColor::getCSSClass($flag->getColor());
$flag_icon = phutil_tag(
'div',
array(
'class' => 'phabricator-flag-icon '.$class,
),
'');
$item = id(new PHUIObjectItemView())
->addHeadIcon($flag_icon)
->setHeader($flag->getHandle()->getFullName())
->setHref($flag->getHandle()->getURI());
$status_open = PhabricatorObjectHandle::STATUS_OPEN;
if ($flag->getHandle()->getStatus() != $status_open) {
$item->setDisabled(true);
}
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("edit/{$phid}/"))
->setWorkflow(true));
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-times')
->setHref($this->getApplicationURI("delete/{$id}/"))
->setWorkflow(true));
if ($flag->getNote()) {
$item->addAttribute($flag->getNote());
}
$item->addIcon(
'none',
phabricator_datetime($flag->getDateCreated(), $viewer));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No flags found.'));
return $result;
}
}
diff --git a/src/applications/fund/editor/FundBackerEditor.php b/src/applications/fund/editor/FundBackerEditor.php
index 403853863b..0736f3339b 100644
--- a/src/applications/fund/editor/FundBackerEditor.php
+++ b/src/applications/fund/editor/FundBackerEditor.php
@@ -1,14 +1,14 @@
<?php
final class FundBackerEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Fund Backing');
}
}
diff --git a/src/applications/fund/editor/FundInitiativeEditEngine.php b/src/applications/fund/editor/FundInitiativeEditEngine.php
index 824f4e009f..a8b90773ad 100644
--- a/src/applications/fund/editor/FundInitiativeEditEngine.php
+++ b/src/applications/fund/editor/FundInitiativeEditEngine.php
@@ -1,152 +1,152 @@
<?php
final class FundInitiativeEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'fund.initiative';
public function getEngineName() {
return pht('Fund');
}
public function getEngineApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Fund Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Fund.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return FundInitiative::initializeNewInitiative($this->getViewer());
}
protected function newObjectQuery() {
return new FundInitiativeQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Initiative');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Initiative: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Initiative');
}
protected function getObjectName() {
return pht('Initiative');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
FundCreateInitiativesCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$v_merchant = $object->getMerchantPHID();
$merchants = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$merchant_options = array();
foreach ($merchants as $merchant) {
$merchant_options[$merchant->getPHID()] = pht(
'Merchant %d %s',
$merchant->getID(),
$merchant->getName());
}
if ($v_merchant && empty($merchant_options[$v_merchant])) {
$merchant_options = array(
$v_merchant => pht('(Restricted Merchant)'),
) + $merchant_options;
}
$merchant_instructions = null;
if (!$merchant_options) {
$merchant_instructions = pht(
'NOTE: You do not control any merchant accounts which can receive '.
'payments from this initiative. When you create an initiative, '.
'you need to specify a merchant account where funds will be paid '.
'to. Create a merchant account in the Phortune application before '.
'creating an initiative in Fund.');
}
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Initiative name.'))
->setConduitTypeDescription(pht('New initiative name.'))
->setTransactionType(
FundInitiativeNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName())
->setIsRequired(true),
id(new PhabricatorSelectEditField())
->setKey('merchantPHID')
->setLabel(pht('Merchant'))
->setDescription(pht('Merchant operating the initiative.'))
->setConduitTypeDescription(pht('New initiative merchant.'))
->setControlInstructions($merchant_instructions)
->setValue($object->getMerchantPHID())
->setTransactionType(
FundInitiativeMerchantTransaction::TRANSACTIONTYPE)
->setOptions($merchant_options)
->setIsRequired(true),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Initiative long description.'))
->setConduitTypeDescription(pht('New initiative description.'))
->setTransactionType(
FundInitiativeDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorRemarkupEditField())
->setKey('risks')
->setLabel(pht('Risks/Challenges'))
->setDescription(pht('Initiative risks and challenges.'))
->setConduitTypeDescription(pht('Initiative risks and challenges.'))
->setTransactionType(
FundInitiativeRisksTransaction::TRANSACTIONTYPE)
->setValue($object->getRisks()),
);
}
}
diff --git a/src/applications/fund/editor/FundInitiativeEditor.php b/src/applications/fund/editor/FundInitiativeEditor.php
index 9175156ffd..139d6073a2 100644
--- a/src/applications/fund/editor/FundInitiativeEditor.php
+++ b/src/applications/fund/editor/FundInitiativeEditor.php
@@ -1,92 +1,92 @@
<?php
final class FundInitiativeEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Fund Initiatives');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this initiative.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
FundInitiativeTransaction::MAILTAG_BACKER =>
pht('Someone backs an initiative.'),
FundInitiativeTransaction::MAILTAG_STATUS =>
pht("An initiative's status changes."),
FundInitiativeTransaction::MAILTAG_OTHER =>
pht('Other initiative activity not listed above occurs.'),
);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('INITIATIVE DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array($object->getOwnerPHID());
}
protected function getMailSubjectPrefix() {
return 'Fund';
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new FundInitiativeReplyHandler())
->setMailReceiver($object);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/fund/phid/FundBackerPHIDType.php b/src/applications/fund/phid/FundBackerPHIDType.php
index 3feff6364a..0c41b6f697 100644
--- a/src/applications/fund/phid/FundBackerPHIDType.php
+++ b/src/applications/fund/phid/FundBackerPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class FundBackerPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'FBAK';
public function getTypeName() {
return pht('Variable');
}
public function newObject() {
return new FundInitiative();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new FundInitiativeQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$initiative = $objects[$phid];
$id = $initiative->getID();
$monogram = $initiative->getMonogram();
$name = $initiative->getName();
$handle->setName($name);
$handle->setFullName("{$monogram} {$name}");
$handle->setURI("/fund/view/{$id}/");
}
}
}
diff --git a/src/applications/fund/phid/FundInitiativePHIDType.php b/src/applications/fund/phid/FundInitiativePHIDType.php
index 3399dc0a3f..d708139cbe 100644
--- a/src/applications/fund/phid/FundInitiativePHIDType.php
+++ b/src/applications/fund/phid/FundInitiativePHIDType.php
@@ -1,78 +1,78 @@
<?php
final class FundInitiativePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'FITV';
public function getTypeName() {
return pht('Fund Initiative');
}
public function newObject() {
return new FundInitiative();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new FundInitiativeQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$initiative = $objects[$phid];
$id = $initiative->getID();
$monogram = $initiative->getMonogram();
$name = $initiative->getName();
if ($initiative->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
$handle->setName($name);
$handle->setFullName("{$monogram} {$name}");
$handle->setURI("/I{$id}");
}
}
public function canLoadNamedObject($name) {
return preg_match('/^I\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new FundInitiativeQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/fund/query/FundBackerQuery.php b/src/applications/fund/query/FundBackerQuery.php
index 2d6e13dfd9..e580e4339d 100644
--- a/src/applications/fund/query/FundBackerQuery.php
+++ b/src/applications/fund/query/FundBackerQuery.php
@@ -1,118 +1,118 @@
<?php
final class FundBackerQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $initiativePHIDs;
private $backerPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withInitiativePHIDs(array $phids) {
$this->initiativePHIDs = $phids;
return $this;
}
public function withBackerPHIDs(array $phids) {
$this->backerPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new FundBacker();
$conn_r = $table->establishConnection('r');
$rows = 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($rows);
}
protected function willFilterPage(array $backers) {
$initiative_phids = mpull($backers, 'getInitiativePHID');
$initiatives = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($initiative_phids)
->execute();
$initiatives = mpull($initiatives, null, 'getPHID');
foreach ($backers as $backer) {
$initiative_phid = $backer->getInitiativePHID();
$initiative = idx($initiatives, $initiative_phid);
$backer->attachInitiative($initiative);
}
return $backers;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
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->initiativePHIDs !== null) {
$where[] = qsprintf(
$conn,
'initiativePHID IN (%Ls)',
$this->initiativePHIDs);
}
if ($this->backerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'backerPHID IN (%Ls)',
$this->backerPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
}
diff --git a/src/applications/fund/query/FundBackerSearchEngine.php b/src/applications/fund/query/FundBackerSearchEngine.php
index ba4b3bc39e..8d4872f9e5 100644
--- a/src/applications/fund/query/FundBackerSearchEngine.php
+++ b/src/applications/fund/query/FundBackerSearchEngine.php
@@ -1,151 +1,151 @@
<?php
final class FundBackerSearchEngine
extends PhabricatorApplicationSearchEngine {
private $initiative;
public function setInitiative(FundInitiative $initiative) {
$this->initiative = $initiative;
return $this;
}
public function getInitiative() {
return $this->initiative;
}
public function getResultTypeDescription() {
return pht('Fund Backers');
}
public function getApplicationClassName() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'backerPHIDs',
$this->readUsersFromRequest($request, 'backers'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new FundBackerQuery());
$query->withStatuses(array(FundBacker::STATUS_PURCHASED));
if ($this->getInitiative()) {
$query->withInitiativePHIDs(
array(
$this->getInitiative()->getPHID(),
));
}
$backer_phids = $saved->getParameter('backerPHIDs');
if ($backer_phids) {
$query->withBackerPHIDs($backer_phids);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$backer_phids = $saved->getParameter('backerPHIDs', array());
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Backers'))
->setName('backers')
->setDatasource(new PhabricatorPeopleDatasource())
->setValue($backer_phids));
}
protected function getURI($path) {
if ($this->getInitiative()) {
return '/fund/backers/'.$this->getInitiative()->getID().'/'.$path;
} else {
return '/fund/backers/'.$path;
}
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All Backers');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $backers,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($backers as $backer) {
$phids[] = $backer->getBackerPHID();
$phids[] = $backer->getInitiativePHID();
}
return $phids;
}
protected function renderResultList(
array $backers,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($backers, 'FundBacker');
$viewer = $this->requireViewer();
$rows = array();
foreach ($backers as $backer) {
$rows[] = array(
$handles[$backer->getInitiativePHID()]->renderLink(),
$handles[$backer->getBackerPHID()]->renderLink(),
$backer->getAmountAsCurrency()->formatForDisplay(),
phabricator_datetime($backer->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setNoDataString(pht('No backers found.'))
->setHeaders(
array(
pht('Initiative'),
pht('Backer'),
pht('Amount'),
pht('Date'),
))
->setColumnClasses(
array(
null,
null,
'wide right',
'right',
));
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
return $result;
}
}
diff --git a/src/applications/fund/query/FundInitiativeQuery.php b/src/applications/fund/query/FundInitiativeQuery.php
index 4b18597873..47d2969220 100644
--- a/src/applications/fund/query/FundInitiativeQuery.php
+++ b/src/applications/fund/query/FundInitiativeQuery.php
@@ -1,77 +1,77 @@
<?php
final class FundInitiativeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $ownerPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withOwnerPHIDs(array $phids) {
$this->ownerPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new FundInitiative();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'i.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'i.phid IN (%Ls)',
$this->phids);
}
if ($this->ownerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'i.ownerPHID IN (%Ls)',
$this->ownerPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'i.status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
protected function getPrimaryTableAlias() {
return 'i';
}
}
diff --git a/src/applications/fund/query/FundInitiativeSearchEngine.php b/src/applications/fund/query/FundInitiativeSearchEngine.php
index e075fe5063..2773d2a150 100644
--- a/src/applications/fund/query/FundInitiativeSearchEngine.php
+++ b/src/applications/fund/query/FundInitiativeSearchEngine.php
@@ -1,154 +1,154 @@
<?php
final class FundInitiativeSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Fund Initiatives');
}
public function getApplicationClassName() {
- return 'PhabricatorFundApplication';
+ return PhabricatorFundApplication::class;
}
public function newQuery() {
return new FundInitiativeQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setKey('ownerPHIDs')
->setAliases(array('owner', 'ownerPHID', 'owners'))
->setLabel(pht('Owners')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Statuses'))
->setOptions(FundInitiative::getStatusNameMap()),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['ownerPHIDs']) {
$query->withOwnerPHIDs($map['ownerPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function getURI($path) {
return '/fund/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['open'] = pht('Open Initiatives');
if ($this->requireViewer()->isLoggedIn()) {
$names['owned'] = pht('Owned Initiatives');
}
$names['all'] = pht('All Initiatives');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'owned':
return $query->setParameter(
'ownerPHIDs',
array(
$this->requireViewer()->getPHID(),
));
case 'open':
return $query->setParameter(
'statuses',
array(
FundInitiative::STATUS_OPEN,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $initiatives,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($initiatives, 'FundInitiative');
$viewer = $this->requireViewer();
$load_phids = array();
foreach ($initiatives as $initiative) {
$load_phids[] = $initiative->getOwnerPHID();
}
if ($initiatives) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($initiatives, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($edge_query->getDestinationPHIDs() as $phid) {
$load_phids[] = $phid;
}
}
$handles = $viewer->loadHandles($load_phids);
$handles = iterator_to_array($handles);
$list = new PHUIObjectItemListView();
foreach ($initiatives as $initiative) {
$owner_handle = $handles[$initiative->getOwnerPHID()];
$item = id(new PHUIObjectItemView())
->setObjectName($initiative->getMonogram())
->setHeader($initiative->getName())
->setHref('/'.$initiative->getMonogram())
->addByline(pht('Owner: %s', $owner_handle->renderLink()));
if ($initiative->isClosed()) {
$item->setDisabled(true);
}
$project_phids = $edge_query->getDestinationPHIDs(
array(
$initiative->getPHID(),
));
$project_handles = array_select_keys($handles, $project_phids);
if ($project_handles) {
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setSlim(true)
->setHandles($project_handles));
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No initiatives found.'));
return $result;
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildEditEngine.php b/src/applications/harbormaster/editor/HarbormasterBuildEditEngine.php
index 9f55965d9c..fcef490256 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildEditEngine.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildEditEngine.php
@@ -1,87 +1,87 @@
<?php
final class HarbormasterBuildEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'harbormaster.build';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Harbormaster Builds');
}
public function getSummaryHeader() {
return pht('Edit Harbormaster Build Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Harbormaster builds.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return HarbormasterBuild::initializeNewBuild($viewer);
}
protected function newObjectQuery() {
return new HarbormasterBuildQuery();
}
protected function newEditableObjectForDocumentation() {
$object = new DifferentialRevision();
$buildable = id(new HarbormasterBuildable())
->attachBuildableObject($object);
return $this->newEditableObject()
->attachBuildable($buildable);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Build');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Build');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Build: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Build');
}
protected function getObjectCreateShortText() {
return pht('Create Build');
}
protected function getObjectName() {
return pht('Build');
}
protected function getEditorURI() {
return '/harbormaster/build/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/harbormaster/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array();
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildPlanEditEngine.php b/src/applications/harbormaster/editor/HarbormasterBuildPlanEditEngine.php
index b7d73f238b..886cae3533 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildPlanEditEngine.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildPlanEditEngine.php
@@ -1,124 +1,124 @@
<?php
final class HarbormasterBuildPlanEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'harbormaster.buildplan';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Harbormaster Build Plans');
}
public function getSummaryHeader() {
return pht('Edit Harbormaster Build Plan Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Harbormaster build plans.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return HarbormasterBuildPlan::initializeNewBuildPlan($viewer);
}
protected function newObjectQuery() {
return new HarbormasterBuildPlanQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Build Plan');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Build Plan');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Build Plan: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Build Plan');
}
protected function getObjectCreateShortText() {
return pht('Create Build Plan');
}
protected function getObjectName() {
return pht('Build Plan');
}
protected function getEditorURI() {
return '/harbormaster/plan/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/harbormaster/plan/';
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return "/harbormaster/plan/{$id}/";
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
HarbormasterCreatePlansCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setIsRequired(true)
->setTransactionType(
HarbormasterBuildPlanNameTransaction::TRANSACTIONTYPE)
->setDescription(pht('The build plan name.'))
->setConduitDescription(pht('Rename the plan.'))
->setConduitTypeDescription(pht('New plan name.'))
->setValue($object->getName()),
);
$metadata_key = HarbormasterBuildPlanBehavior::getTransactionMetadataKey();
$behaviors = HarbormasterBuildPlanBehavior::newPlanBehaviors();
foreach ($behaviors as $behavior) {
$key = $behavior->getKey();
// Get the raw key off the object so that we don't reset stuff to
// default values by mistake if a behavior goes missing somehow.
$storage_key = HarbormasterBuildPlanBehavior::getStorageKeyForBehaviorKey(
$key);
$behavior_option = $object->getPlanProperty($storage_key);
if (!phutil_nonempty_string($behavior_option)) {
$behavior_option = $behavior->getPlanOption($object)->getKey();
}
$fields[] = id(new PhabricatorSelectEditField())
->setIsFormField(false)
->setKey(sprintf('behavior.%s', $behavior->getKey()))
->setMetadataValue($metadata_key, $behavior->getKey())
->setLabel(pht('Behavior: %s', $behavior->getName()))
->setTransactionType(
HarbormasterBuildPlanBehaviorTransaction::TRANSACTIONTYPE)
->setValue($behavior_option)
->setOptions($behavior->getOptionMap());
}
return $fields;
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildPlanEditor.php b/src/applications/harbormaster/editor/HarbormasterBuildPlanEditor.php
index 1b340b6524..bf9d938bc8 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildPlanEditor.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildPlanEditor.php
@@ -1,33 +1,33 @@
<?php
final class HarbormasterBuildPlanEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Harbormaster Build Plans');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this build plan.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildStepEditEngine.php b/src/applications/harbormaster/editor/HarbormasterBuildStepEditEngine.php
index d54832cad1..a93478a086 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildStepEditEngine.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildStepEditEngine.php
@@ -1,107 +1,107 @@
<?php
final class HarbormasterBuildStepEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'harbormaster.buildstep';
private $buildPlan;
public function setBuildPlan(HarbormasterBuildPlan $build_plan) {
$this->buildPlan = $build_plan;
return $this;
}
public function getBuildPlan() {
if ($this->buildPlan === null) {
throw new PhutilInvalidStateException('setBuildPlan');
}
return $this->buildPlan;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Harbormaster Build Steps');
}
public function getSummaryHeader() {
return pht('Edit Harbormaster Build Step Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Harbormaster build steps.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$plan = HarbormasterBuildPlan::initializeNewBuildPlan($viewer);
$this->setBuildPlan($plan);
$plan = $this->getBuildPlan();
$step = HarbormasterBuildStep::initializeNewStep($viewer);
$step->setBuildPlanPHID($plan->getPHID());
$step->attachBuildPlan($plan);
return $step;
}
protected function newObjectQuery() {
return new HarbormasterBuildStepQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Build Step');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Build Step');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Build Step: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Build Step');
}
protected function getObjectCreateShortText() {
return pht('Create Build Step');
}
protected function getObjectName() {
return pht('Build Step');
}
protected function getEditorURI() {
return '/harbormaster/step/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/harbormaster/step/';
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return "/harbormaster/step/{$id}/";
}
protected function buildCustomEditFields($object) {
$fields = array();
return $fields;
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildStepEditor.php b/src/applications/harbormaster/editor/HarbormasterBuildStepEditor.php
index 8206edee4d..dec2a70a55 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildStepEditor.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildStepEditor.php
@@ -1,101 +1,101 @@
<?php
final class HarbormasterBuildStepEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Harbormaster Build Steps');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = HarbormasterBuildStepTransaction::TYPE_CREATE;
$types[] = HarbormasterBuildStepTransaction::TYPE_NAME;
$types[] = HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON;
$types[] = HarbormasterBuildStepTransaction::TYPE_DESCRIPTION;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case HarbormasterBuildStepTransaction::TYPE_CREATE:
return null;
case HarbormasterBuildStepTransaction::TYPE_NAME:
if ($this->getIsNewObject()) {
return null;
}
return $object->getName();
case HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON:
if ($this->getIsNewObject()) {
return null;
}
return $object->getDetail('dependsOn', array());
case HarbormasterBuildStepTransaction::TYPE_DESCRIPTION:
if ($this->getIsNewObject()) {
return null;
}
return $object->getDescription();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case HarbormasterBuildStepTransaction::TYPE_CREATE:
return true;
case HarbormasterBuildStepTransaction::TYPE_NAME:
case HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON:
case HarbormasterBuildStepTransaction::TYPE_DESCRIPTION:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case HarbormasterBuildStepTransaction::TYPE_CREATE:
return;
case HarbormasterBuildStepTransaction::TYPE_NAME:
return $object->setName($xaction->getNewValue());
case HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON:
return $object->setDetail('dependsOn', $xaction->getNewValue());
case HarbormasterBuildStepTransaction::TYPE_DESCRIPTION:
return $object->setDescription($xaction->getNewValue());
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case HarbormasterBuildStepTransaction::TYPE_CREATE:
case HarbormasterBuildStepTransaction::TYPE_NAME:
case HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON:
case HarbormasterBuildStepTransaction::TYPE_DESCRIPTION:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php b/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php
index 146caf9f2c..1746bf97b5 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php
@@ -1,14 +1,14 @@
<?php
final class HarbormasterBuildTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Harbormaster Builds');
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildableEditEngine.php b/src/applications/harbormaster/editor/HarbormasterBuildableEditEngine.php
index bd60eeb53b..9e16038bc7 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildableEditEngine.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildableEditEngine.php
@@ -1,84 +1,84 @@
<?php
final class HarbormasterBuildableEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'harbormaster.buildable';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Harbormaster Buildables');
}
public function getSummaryHeader() {
return pht('Edit Harbormaster Buildable Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Harbormaster buildables.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return HarbormasterBuildable::initializeNewBuildable($viewer);
}
protected function newObjectQuery() {
return new HarbormasterBuildableQuery();
}
protected function newEditableObjectForDocumentation() {
$object = new DifferentialRevision();
return $this->newEditableObject()
->attachBuildableObject($object);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Buildable');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Buildable');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Buildable: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Buildable');
}
protected function getObjectCreateShortText() {
return pht('Create Buildable');
}
protected function getObjectName() {
return pht('Buildable');
}
protected function getEditorURI() {
return '/harbormaster/buildable/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/harbormaster/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array();
}
}
diff --git a/src/applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php b/src/applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php
index 895c89f858..df8b20864a 100644
--- a/src/applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php
+++ b/src/applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php
@@ -1,14 +1,14 @@
<?php
final class HarbormasterBuildableTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Harbormaster Buildables');
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php
index 29256afd96..180bb6ed82 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class HarbormasterBuildArtifactPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMBA';
public function getTypeName() {
return pht('Build Artifact');
}
public function newObject() {
return new HarbormasterBuildArtifact();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildArtifactQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$artifact = $objects[$phid];
$artifact_id = $artifact->getID();
$handle->setName(pht('Build Artifact %d', $artifact_id));
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php
index a2fa58fe79..faa26fab35 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class HarbormasterBuildLogPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMCL';
public function getTypeName() {
return pht('Build Log');
}
public function newObject() {
return new HarbormasterBuildLog();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildLogQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$build_log = $objects[$phid];
$handle
->setName(pht('Build Log %d', $build_log->getID()))
->setURI($build_log->getURI());
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php
index 27551f13a8..be4bbd1256 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class HarbormasterBuildPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMBD';
public function getTypeName() {
return pht('Build');
}
public function newObject() {
return new HarbormasterBuild();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$build = $objects[$phid];
$build_id = $build->getID();
$name = $build->getName();
$handle->setName(pht('Build %d: %s', $build_id, $name));
$handle->setURI("/harbormaster/build/{$build_id}/");
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php
index 86aacfb8d3..0b4f55f6e3 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php
@@ -1,44 +1,44 @@
<?php
final class HarbormasterBuildPlanPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMCP';
public function getTypeName() {
return pht('Build Plan');
}
public function getTypeIcon() {
return 'fa-cubes';
}
public function newObject() {
return new HarbormasterBuildPlan();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildPlanQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$build_plan = $objects[$phid];
$id = $build_plan->getID();
$handles[$phid]->setName(pht('Plan %d %s', $id, $build_plan->getName()));
$handles[$phid]->setURI('/harbormaster/plan/'.$id.'/');
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php
index 63e9bc6a12..75ede8a632 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class HarbormasterBuildStepPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMCS';
public function getTypeName() {
return pht('Build Step');
}
public function newObject() {
return new HarbormasterBuildStep();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildStepQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$build_step = $objects[$phid];
$id = $build_step->getID();
$name = $build_step->getName();
$handle
->setName($name)
->setFullName(pht('Build Step %d: %s', $id, $name))
->setURI("/harbormaster/step/view/{$id}/");
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php
index b20d6dc0a4..002563a3f9 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php
@@ -1,47 +1,47 @@
<?php
final class HarbormasterBuildTargetPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMBT';
public function getTypeName() {
return pht('Build Target');
}
public function newObject() {
return new HarbormasterBuildTarget();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildTargetQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$target = $objects[$phid];
$target_id = $target->getID();
// Build target don't currently have their own page, so just point
// the user at the build until we have one.
$build = $target->getBuild();
$build_id = $build->getID();
$uri = "/harbormaster/build/{$build_id}/";
$handle->setName(pht('Build Target %d', $target_id));
$handle->setURI($uri);
}
}
}
diff --git a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php
index 674393dfc7..fac63376a4 100644
--- a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php
+++ b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php
@@ -1,88 +1,88 @@
<?php
final class HarbormasterBuildablePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HMBB';
public function getTypeName() {
return pht('Buildable');
}
public function newObject() {
return new HarbormasterBuildable();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HarbormasterBuildableQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
$target_phids = array();
foreach ($objects as $phid => $object) {
$target_phids[] = $object->getBuildablePHID();
}
$target_handles = $viewer->loadHandles($target_phids);
foreach ($handles as $phid => $handle) {
$buildable = $objects[$phid];
$id = $buildable->getID();
$buildable_phid = $buildable->getBuildablePHID();
$target = $target_handles[$buildable_phid];
$target_name = $target->getFullName();
$uri = $buildable->getURI();
$monogram = $buildable->getMonogram();
$handle
->setURI($uri)
->setName($monogram)
->setFullName("{$monogram}: {$target_name}");
}
}
public function canLoadNamedObject($name) {
return preg_match('/^B\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new HarbormasterBuildableQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterArtifactSearchEngine.php b/src/applications/harbormaster/query/HarbormasterArtifactSearchEngine.php
index b7e93b2320..a839163879 100644
--- a/src/applications/harbormaster/query/HarbormasterArtifactSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterArtifactSearchEngine.php
@@ -1,93 +1,93 @@
<?php
final class HarbormasterArtifactSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Artifacts');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildArtifactQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Targets'))
->setKey('buildTargetPHIDs')
->setAliases(
array(
'buildTargetPHID',
'buildTargets',
'buildTarget',
'targetPHIDs',
'targetPHID',
'targets',
'target',
))
->setDescription(
pht('Search for artifacts attached to particular build targets.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['buildTargetPHIDs']) {
$query->withBuildTargetPHIDs($map['buildTargetPHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/artifact/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Artifacts'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $artifacts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($artifacts, 'HarbormasterBuildArtifact');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($artifacts as $artifact) {
$id = $artifact->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Artifact %d', $id));
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No artifacts found.'));
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
index 59d4c07d2f..a1b40c6b1e 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
@@ -1,113 +1,113 @@
<?php
final class HarbormasterBuildArtifactQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $buildTargetPHIDs;
private $artifactTypes;
private $artifactIndexes;
private $keyBuildPHID;
private $keyBuildGeneration;
private $isReleased;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
public function withArtifactTypes(array $artifact_types) {
$this->artifactTypes = $artifact_types;
return $this;
}
public function withArtifactIndexes(array $artifact_indexes) {
$this->artifactIndexes = $artifact_indexes;
return $this;
}
public function withIsReleased($released) {
$this->isReleased = $released;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildArtifact();
}
protected function willFilterPage(array $page) {
$build_targets = array();
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $build_log) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->buildTargetPHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
if ($this->artifactTypes !== null) {
$where[] = qsprintf(
$conn,
'artifactType in (%Ls)',
$this->artifactTypes);
}
if ($this->artifactIndexes !== null) {
$where[] = qsprintf(
$conn,
'artifactIndex IN (%Ls)',
$this->artifactIndexes);
}
if ($this->isReleased !== null) {
$where[] = qsprintf(
$conn,
'isReleased = %d',
(int)$this->isReleased);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
index f62919f989..1bd48d4d05 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
@@ -1,86 +1,86 @@
<?php
final class HarbormasterBuildLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPHIDs;
private $buildTargetPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildLog();
}
protected function willFilterPage(array $page) {
$build_targets = array();
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $build_log) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->buildTargetPHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildLogSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildLogSearchEngine.php
index 3698238b12..473311064f 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildLogSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildLogSearchEngine.php
@@ -1,79 +1,79 @@
<?php
final class HarbormasterBuildLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Build Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildLogQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Build Targets'))
->setKey('buildTargetPHIDs')
->setAliases(
array(
'buildTargetPHID',
'buildTargets',
'buildTarget',
'targetPHIDs',
'targetPHID',
'targets',
'target',
))
->setDescription(
pht('Search for logs that belong to a particular build target.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['buildTargetPHIDs']) {
$query->withBuildTargetPHIDs($map['buildTargetPHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/log/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Builds'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $builds,
PhabricatorSavedQuery $query,
array $handles) {
// For now, this SearchEngine is only for driving the API.
throw new PhutilMethodNotImplementedException();
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
index 393ca0a493..779d256117 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
@@ -1,88 +1,88 @@
<?php
final class HarbormasterBuildMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $receiverPHIDs;
private $consumed;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withReceiverPHIDs(array $phids) {
$this->receiverPHIDs = $phids;
return $this;
}
public function withConsumed($consumed) {
$this->consumed = $consumed;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildMessage();
}
protected function willFilterPage(array $page) {
$receiver_phids = array_filter(mpull($page, 'getReceiverPHID'));
if ($receiver_phids) {
$receivers = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($receiver_phids)
->setParentQuery($this)
->execute();
$receivers = mpull($receivers, null, 'getPHID');
} else {
$receivers = array();
}
foreach ($page as $key => $message) {
$receiver_phid = $message->getReceiverPHID();
if (empty($receivers[$receiver_phid])) {
unset($page[$key]);
$this->didRejectResult($message);
continue;
}
$message->attachReceiver($receivers[$receiver_phid]);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->receiverPHIDs !== null) {
$where[] = qsprintf(
$conn,
'receiverPHID IN (%Ls)',
$this->receiverPHIDs);
}
if ($this->consumed !== null) {
$where[] = qsprintf(
$conn,
'isConsumed = %d',
(int)$this->consumed);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
index c8514b2186..04a14d32b5 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
@@ -1,148 +1,148 @@
<?php
final class HarbormasterBuildPlanQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $datasourceQuery;
private $planAutoKeys;
private $needBuildSteps;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function withPlanAutoKeys(array $keys) {
$this->planAutoKeys = $keys;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new HarbormasterBuildPlanNameNgrams(),
$ngrams);
}
public function needBuildSteps($need) {
$this->needBuildSteps = $need;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildPlan();
}
protected function didFilterPage(array $page) {
if ($this->needBuildSteps) {
$plan_phids = mpull($page, 'getPHID');
$steps = id(new HarbormasterBuildStepQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withBuildPlanPHIDs($plan_phids)
->execute();
$steps = mgroup($steps, 'getBuildPlanPHID');
foreach ($page as $plan) {
$plan_steps = idx($steps, $plan->getPHID(), array());
$plan->attachBuildSteps($plan_steps);
}
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'plan.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'plan.phid IN (%Ls)',
$this->phids);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'plan.planStatus IN (%Ls)',
$this->statuses);
}
if (!phutil_nonempty_string($this->datasourceQuery)) {
$where[] = qsprintf(
$conn,
'plan.name LIKE %>',
$this->datasourceQuery);
}
if ($this->planAutoKeys !== null) {
$where[] = qsprintf(
$conn,
'plan.planAutoKey IN (%Ls)',
$this->planAutoKeys);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'plan';
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'column' => 'name',
'type' => 'string',
'reverse' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php
index 709df7f94c..930308e496 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php
@@ -1,138 +1,138 @@
<?php
final class HarbormasterBuildPlanSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Build Plans');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildPlanQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for namespaces by name substring.')),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Status'))
->setKey('status')
->setAliases(array('statuses'))
->setOptions(
array(
HarbormasterBuildPlan::STATUS_ACTIVE => pht('Active'),
HarbormasterBuildPlan::STATUS_DISABLED => pht('Disabled'),
)),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['status']) {
$query->withStatuses($map['status']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/plan/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'active' => pht('Active Plans'),
'all' => pht('All Plans'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter(
'status',
array(
HarbormasterBuildPlan::STATUS_ACTIVE,
));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $plans,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($plans, 'HarbormasterBuildPlan');
$viewer = $this->requireViewer();
if ($plans) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($plans, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
}
$list = new PHUIObjectItemListView();
foreach ($plans as $plan) {
$id = $plan->getID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Plan %d', $id))
->setHeader($plan->getName());
if ($plan->isDisabled()) {
$item->setDisabled(true);
}
if ($plan->isAutoplan()) {
$item->addIcon('fa-lock grey', pht('Autoplan'));
}
$item->setHref($this->getApplicationURI("plan/{$id}/"));
$phid = $plan->getPHID();
$project_phids = $edge_query->getDestinationPHIDs(array($phid));
$project_handles = $viewer->loadHandles($project_phids);
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setNoDataString(pht('No Projects'))
->setSlim(true)
->setHandles($project_handles));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No build plans found.'));
return $result;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildQuery.php b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
index a397f5968a..e1260d9175 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
@@ -1,229 +1,229 @@
<?php
final class HarbormasterBuildQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildStatuses;
private $buildablePHIDs;
private $buildPlanPHIDs;
private $initiatorPHIDs;
private $needBuildTargets;
private $autobuilds;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildStatuses(array $build_statuses) {
$this->buildStatuses = $build_statuses;
return $this;
}
public function withBuildablePHIDs(array $buildable_phids) {
$this->buildablePHIDs = $buildable_phids;
return $this;
}
public function withBuildPlanPHIDs(array $build_plan_phids) {
$this->buildPlanPHIDs = $build_plan_phids;
return $this;
}
public function withInitiatorPHIDs(array $initiator_phids) {
$this->initiatorPHIDs = $initiator_phids;
return $this;
}
public function withAutobuilds($with_autobuilds) {
$this->autobuilds = $with_autobuilds;
return $this;
}
public function needBuildTargets($need_targets) {
$this->needBuildTargets = $need_targets;
return $this;
}
public function newResultObject() {
return new HarbormasterBuild();
}
protected function willFilterPage(array $page) {
$buildables = array();
$buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($buildable_phids) {
$buildables = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildable_phids)
->setParentQuery($this)
->execute();
$buildables = mpull($buildables, null, 'getPHID');
}
foreach ($page as $key => $build) {
$buildable_phid = $build->getBuildablePHID();
if (empty($buildables[$buildable_phid])) {
unset($page[$key]);
continue;
}
$build->attachBuildable($buildables[$buildable_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
$plans = array();
$plan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
if ($plan_phids) {
$plans = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($plan_phids)
->setParentQuery($this)
->execute();
$plans = mpull($plans, null, 'getPHID');
}
foreach ($page as $key => $build) {
$plan_phid = $build->getBuildPlanPHID();
$build->attachBuildPlan(idx($plans, $plan_phid));
}
$build_phids = mpull($page, 'getPHID');
$messages = id(new HarbormasterBuildMessage())->loadAllWhere(
'receiverPHID IN (%Ls) AND isConsumed = 0 ORDER BY id ASC',
$build_phids);
$messages = mgroup($messages, 'getReceiverPHID');
foreach ($page as $build) {
$unprocessed_messages = idx($messages, $build->getPHID(), array());
$build->attachUnprocessedMessages($unprocessed_messages);
}
if ($this->needBuildTargets) {
$targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withBuildPHIDs($build_phids)
->execute();
// TODO: Some day, when targets have dependencies, we should toposort
// these. For now, just put them into chronological order.
$targets = array_reverse($targets);
$targets = mgroup($targets, 'getBuildPHID');
foreach ($page as $build) {
$build_targets = idx($targets, $build->getPHID(), array());
foreach ($build_targets as $phid => $target) {
if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
unset($build_targets[$phid]);
}
}
$build->attachBuildTargets($build_targets);
}
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'b.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'b.phid in (%Ls)',
$this->phids);
}
if ($this->buildStatuses !== null) {
$where[] = qsprintf(
$conn,
'b.buildStatus in (%Ls)',
$this->buildStatuses);
}
if ($this->buildablePHIDs !== null) {
$where[] = qsprintf(
$conn,
'b.buildablePHID IN (%Ls)',
$this->buildablePHIDs);
}
if ($this->buildPlanPHIDs !== null) {
$where[] = qsprintf(
$conn,
'b.buildPlanPHID IN (%Ls)',
$this->buildPlanPHIDs);
}
if ($this->initiatorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'b.initiatorPHID IN (%Ls)',
$this->initiatorPHIDs);
}
if ($this->autobuilds !== null) {
if ($this->autobuilds) {
$where[] = qsprintf(
$conn,
'p.planAutoKey IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'p.planAutoKey IS NULL');
}
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinPlanTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T p ON b.buildPlanPHID = p.phid',
id(new HarbormasterBuildPlan())->getTableName());
}
return $joins;
}
private function shouldJoinPlanTable() {
if ($this->autobuilds !== null) {
return true;
}
return false;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
protected function getPrimaryTableAlias() {
return 'b';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildSearchEngine.php
index b8140d84f6..4b722c4990 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildSearchEngine.php
@@ -1,141 +1,141 @@
<?php
final class HarbormasterBuildSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Builds');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Build Plans'))
->setKey('plans')
->setAliases(array('plan'))
->setDescription(
pht('Search for builds running a given build plan.'))
->setDatasource(new HarbormasterBuildPlanDatasource()),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Buildables'))
->setKey('buildables')
->setAliases(array('buildable'))
->setDescription(
pht('Search for builds running against particular buildables.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setAliases(array('status'))
->setDescription(
pht('Search for builds with given statuses.'))
->setDatasource(new HarbormasterBuildStatusDatasource()),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Initiators'))
->setKey('initiators')
->setAliases(array('initiator'))
->setDescription(
pht(
'Search for builds started by someone or something in particular.'))
->setDatasource(new HarbormasterBuildInitiatorDatasource()),
);
}
protected function getHiddenFields() {
return array(
'buildables',
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['plans']) {
$query->withBuildPlanPHIDs($map['plans']);
}
if ($map['buildables']) {
$query->withBuildablePHIDs($map['buildables']);
}
if ($map['statuses']) {
$query->withBuildStatuses($map['statuses']);
}
if ($map['initiators']) {
$query->withInitiatorPHIDs($map['initiators']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/build/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'initiated' => pht('My Builds'),
'all' => pht('All Builds'),
'waiting' => pht('Waiting'),
'active' => pht('Active'),
'completed' => pht('Completed'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'initiated':
$viewer = $this->requireViewer();
return $query->setParameter('initiators', array($viewer->getPHID()));
case 'all':
return $query;
case 'waiting':
return $query
->setParameter(
'statuses',
HarbormasterBuildStatus::getWaitingStatusConstants());
case 'active':
return $query
->setParameter(
'statuses',
HarbormasterBuildStatus::getActiveStatusConstants());
case 'completed':
return $query
->setParameter(
'statuses',
HarbormasterBuildStatus::getCompletedStatusConstants());
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $builds,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($builds, 'HarbormasterBuild');
$viewer = $this->requireViewer();
$list = id(new HarbormasterBuildView())
->setViewer($viewer)
->setBuilds($builds)
->newObjectList();
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No builds found.'));
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
index 93010071e2..3c91b578c7 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
@@ -1,85 +1,85 @@
<?php
final class HarbormasterBuildStepQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPlanPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildPlanPHIDs(array $phids) {
$this->buildPlanPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildStep();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->buildPlanPHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildPlanPHID in (%Ls)',
$this->buildPlanPHIDs);
}
return $where;
}
protected function willFilterPage(array $page) {
$plans = array();
$buildplan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
if ($buildplan_phids) {
$plans = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildplan_phids)
->setParentQuery($this)
->execute();
$plans = mpull($plans, null, 'getPHID');
}
foreach ($page as $key => $build) {
$buildable_phid = $build->getBuildPlanPHID();
if (empty($plans[$buildable_phid])) {
unset($page[$key]);
continue;
}
$build->attachBuildPlan($plans[$buildable_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildStepSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildStepSearchEngine.php
index b866a1dbc9..3ff1707edf 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildStepSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildStepSearchEngine.php
@@ -1,58 +1,58 @@
<?php
final class HarbormasterBuildStepSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Build Steps');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildStepQuery();
}
protected function buildCustomSearchFields() {
return array();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function getURI($path) {
return '/harbormaster/step/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Steps'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $plans,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($plans, 'HarbormasterBuildStep');
return null;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
index a93aff60bd..5abdbbd5a8 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
@@ -1,209 +1,209 @@
<?php
final class HarbormasterBuildTargetQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPHIDs;
private $buildGenerations;
private $dateCreatedMin;
private $dateCreatedMax;
private $dateStartedMin;
private $dateStartedMax;
private $dateCompletedMin;
private $dateCompletedMax;
private $statuses;
private $needBuildSteps;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildPHIDs(array $build_phids) {
$this->buildPHIDs = $build_phids;
return $this;
}
public function withBuildGenerations(array $build_generations) {
$this->buildGenerations = $build_generations;
return $this;
}
public function withDateCreatedBetween($min, $max) {
$this->dateCreatedMin = $min;
$this->dateCreatedMax = $max;
return $this;
}
public function withDateStartedBetween($min, $max) {
$this->dateStartedMin = $min;
$this->dateStartedMax = $max;
return $this;
}
public function withDateCompletedBetween($min, $max) {
$this->dateCompletedMin = $min;
$this->dateCompletedMax = $max;
return $this;
}
public function withTargetStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needBuildSteps($need_build_steps) {
$this->needBuildSteps = $need_build_steps;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildTarget();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->buildPHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildPHID in (%Ls)',
$this->buildPHIDs);
}
if ($this->buildGenerations !== null) {
$where[] = qsprintf(
$conn,
'buildGeneration in (%Ld)',
$this->buildGenerations);
}
if ($this->dateCreatedMin !== null) {
$where[] = qsprintf(
$conn,
'dateCreated >= %d',
$this->dateCreatedMin);
}
if ($this->dateCreatedMax !== null) {
$where[] = qsprintf(
$conn,
'dateCreated <= %d',
$this->dateCreatedMax);
}
if ($this->dateStartedMin !== null) {
$where[] = qsprintf(
$conn,
'dateStarted >= %d',
$this->dateStartedMin);
}
if ($this->dateStartedMax !== null) {
$where[] = qsprintf(
$conn,
'dateStarted <= %d',
$this->dateStartedMax);
}
if ($this->dateCompletedMin !== null) {
$where[] = qsprintf(
$conn,
'dateCompleted >= %d',
$this->dateCompletedMin);
}
if ($this->dateCompletedMax !== null) {
$where[] = qsprintf(
$conn,
'dateCompleted <= %d',
$this->dateCompletedMax);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'targetStatus IN (%Ls)',
$this->statuses);
}
return $where;
}
protected function didFilterPage(array $page) {
if ($this->needBuildSteps) {
$step_phids = array();
foreach ($page as $target) {
$step_phids[] = $target->getBuildStepPHID();
}
$steps = id(new HarbormasterBuildStepQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($step_phids)
->execute();
$steps = mpull($steps, null, 'getPHID');
foreach ($page as $target) {
$target->attachBuildStep(
idx($steps, $target->getBuildStepPHID()));
}
}
return $page;
}
protected function willFilterPage(array $page) {
$builds = array();
$build_phids = array_filter(mpull($page, 'getBuildPHID'));
if ($build_phids) {
$builds = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($build_phids)
->setParentQuery($this)
->execute();
$builds = mpull($builds, null, 'getPHID');
}
foreach ($page as $key => $build_target) {
$build_phid = $build_target->getBuildPHID();
if (empty($builds[$build_phid])) {
unset($page[$key]);
continue;
}
$build_target->attachBuild($builds[$build_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildTargetSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildTargetSearchEngine.php
index db7d6f7c87..5ad5919eb9 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildTargetSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildTargetSearchEngine.php
@@ -1,131 +1,131 @@
<?php
final class HarbormasterBuildTargetSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Build Targets');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildTargetQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Builds'))
->setKey('buildPHIDs')
->setAliases(array('build', 'builds', 'buildPHID'))
->setDescription(
pht('Search for targets of a given build.'))
->setDatasource(new HarbormasterBuildPlanDatasource()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart')
->setDescription(
pht('Search for targets created on or after a particular date.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd')
->setDescription(
pht('Search for targets created on or before a particular date.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Started After'))
->setKey('startedStart')
->setDescription(
pht('Search for targets started on or after a particular date.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Started Before'))
->setKey('startedEnd')
->setDescription(
pht('Search for targets started on or before a particular date.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Completed After'))
->setKey('completedStart')
->setDescription(
pht('Search for targets completed on or after a particular date.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Completed Before'))
->setKey('completedEnd')
->setDescription(
pht('Search for targets completed on or before a particular date.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setAliases(array('status'))
->setDescription(
pht('Search for targets with given statuses.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['buildPHIDs']) {
$query->withBuildPHIDs($map['buildPHIDs']);
}
if ($map['createdStart'] !== null || $map['createdEnd'] !== null) {
$query->withDateCreatedBetween(
$map['createdStart'],
$map['createdEnd']);
}
if ($map['startedStart'] !== null || $map['startedEnd'] !== null) {
$query->withDateStartedBetween(
$map['startedStart'],
$map['startedEnd']);
}
if ($map['completedStart'] !== null || $map['completedEnd'] !== null) {
$query->withDateCompletedBetween(
$map['completedStart'],
$map['completedEnd']);
}
if ($map['statuses']) {
$query->withTargetStatuses($map['statuses']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/target/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Targets'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $builds,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($builds, 'HarbormasterBuildTarget');
// Currently, this only supports the "harbormaster.target.search"
// API method.
throw new PhutilMethodNotImplementedException();
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php b/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
index edfe102ca2..049ac7f4b7 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildUnitMessageQuery.php
@@ -1,91 +1,91 @@
<?php
final class HarbormasterBuildUnitMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $targetPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildTargetPHIDs(array $target_phids) {
$this->targetPHIDs = $target_phids;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildUnitMessage();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->targetPHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildTargetPHID in (%Ls)',
$this->targetPHIDs);
}
return $where;
}
protected function didFilterPage(array $messages) {
$indexes = array();
foreach ($messages as $message) {
$index = $message->getNameIndex();
if (strlen($index)) {
$indexes[$index] = $index;
}
}
if ($indexes) {
$map = HarbormasterString::newIndexMap($indexes);
foreach ($messages as $message) {
$index = $message->getNameIndex();
if (!strlen($index)) {
continue;
}
$name = idx($map, $index);
if ($name === null) {
$name = pht('Unknown Unit Message ("%s")', $index);
}
$message->setName($name);
}
}
return $messages;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
index cf907a2dc3..fea8ba926d 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
@@ -1,180 +1,180 @@
<?php
final class HarbormasterBuildableQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildablePHIDs;
private $containerPHIDs;
private $statuses;
private $manualBuildables;
private $needContainerObjects;
private $needBuilds;
private $needTargets;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildablePHIDs(array $buildable_phids) {
$this->buildablePHIDs = $buildable_phids;
return $this;
}
public function withContainerPHIDs(array $container_phids) {
$this->containerPHIDs = $container_phids;
return $this;
}
public function withManualBuildables($manual) {
$this->manualBuildables = $manual;
return $this;
}
public function needContainerObjects($need) {
$this->needContainerObjects = $need;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needBuilds($need) {
$this->needBuilds = $need;
return $this;
}
public function needTargets($need) {
$this->needTargets = $need;
return $this;
}
public function newResultObject() {
return new HarbormasterBuildable();
}
protected function willFilterPage(array $page) {
$buildables = array();
$buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($buildable_phids) {
$buildables = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildable_phids)
->setParentQuery($this)
->execute();
$buildables = mpull($buildables, null, 'getPHID');
}
foreach ($page as $key => $buildable) {
$buildable_phid = $buildable->getBuildablePHID();
if (empty($buildables[$buildable_phid])) {
unset($page[$key]);
continue;
}
$buildable->attachBuildableObject($buildables[$buildable_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
if ($this->needContainerObjects) {
$container_phids = array_filter(mpull($page, 'getContainerPHID'));
if ($container_phids) {
$containers = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($container_phids)
->setParentQuery($this)
->execute();
$containers = mpull($containers, null, 'getPHID');
} else {
$containers = array();
}
foreach ($page as $key => $buildable) {
$container_phid = $buildable->getContainerPHID();
$buildable->attachContainerObject(idx($containers, $container_phid));
}
}
if ($this->needBuilds || $this->needTargets) {
$builds = id(new HarbormasterBuildQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withBuildablePHIDs(mpull($page, 'getPHID'))
->needBuildTargets($this->needTargets)
->execute();
$builds = mgroup($builds, 'getBuildablePHID');
foreach ($page as $key => $buildable) {
$buildable->attachBuilds(idx($builds, $buildable->getPHID(), array()));
}
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->buildablePHIDs !== null) {
$where[] = qsprintf(
$conn,
'buildablePHID IN (%Ls)',
$this->buildablePHIDs);
}
if ($this->containerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'containerPHID in (%Ls)',
$this->containerPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'buildableStatus in (%Ls)',
$this->statuses);
}
if ($this->manualBuildables !== null) {
$where[] = qsprintf(
$conn,
'isManualBuildable = %d',
(int)$this->manualBuildables);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php b/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php
index 36f5dc89c2..88fbd8f8b6 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildableSearchEngine.php
@@ -1,188 +1,188 @@
<?php
final class HarbormasterBuildableSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Harbormaster Buildables');
}
public function getApplicationClassName() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function newQuery() {
return new HarbormasterBuildableQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchStringListField())
->setKey('objectPHIDs')
->setAliases(array('objects'))
->setLabel(pht('Objects'))
->setPlaceholder(pht('rXabcdef, PHID-DIFF-1234, ...'))
->setDescription(pht('Search for builds of particular objects.')),
id(new PhabricatorSearchStringListField())
->setKey('containerPHIDs')
->setAliases(array('containers'))
->setLabel(pht('Containers'))
->setPlaceholder(pht('rXYZ, R123, D456, ...'))
->setDescription(
pht('Search for builds by containing revision or repository.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Statuses'))
->setOptions(HarbormasterBuildableStatus::getOptionMap())
->setDescription(pht('Search for builds by buildable status.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Manual'))
->setKey('manual')
->setDescription(
pht('Search for only manual or automatic buildables.'))
->setOptions(
pht('(Show All)'),
pht('Show Only Manual Builds'),
pht('Show Only Automated Builds')),
);
}
private function resolvePHIDs(array $names) {
$viewer = $this->requireViewer();
$objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withNames($names)
->execute();
// TODO: Instead of using string lists, we should ideally be using some
// kind of smart field with resolver logic that can help users type the
// right stuff. For now, just return a bogus value here so nothing matches
// but the form doesn't explode.
if (!$objects) {
return array('-');
}
return mpull($objects, 'getPHID');
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['objectPHIDs']) {
$phids = $this->resolvePHIDs($map['objectPHIDs']);
if ($phids) {
$query->withBuildablePHIDs($phids);
}
}
if ($map['containerPHIDs']) {
$phids = $this->resolvePHIDs($map['containerPHIDs']);
if ($phids) {
$query->withContainerPHIDs($phids);
}
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['manual'] !== null) {
$query->withManualBuildables($map['manual']);
}
return $query;
}
protected function getURI($path) {
return '/harbormaster/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Buildables'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $buildables,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($buildables, 'HarbormasterBuildable');
$viewer = $this->requireViewer();
$phids = array();
foreach ($buildables as $buildable) {
$phids[] = $buildable->getBuildableObject()
->getHarbormasterBuildableDisplayPHID();
$phids[] = $buildable->getContainerPHID();
$phids[] = $buildable->getBuildablePHID();
}
$handles = $viewer->loadHandles($phids);
$list = new PHUIObjectItemListView();
foreach ($buildables as $buildable) {
$id = $buildable->getID();
$display_phid = $buildable->getBuildableObject()
->getHarbormasterBuildableDisplayPHID();
$container_phid = $buildable->getContainerPHID();
$buildable_phid = $buildable->getBuildablePHID();
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Buildable %d', $buildable->getID()));
if ($display_phid) {
$handle = $handles[$display_phid];
$item->setHeader($handle->getFullName());
}
if ($container_phid && ($container_phid != $display_phid)) {
$handle = $handles[$container_phid];
$item->addAttribute($handle->getName());
}
if ($buildable_phid && ($buildable_phid != $display_phid)) {
$handle = $handles[$buildable_phid];
$item->addAttribute($handle->getFullName());
}
$item->setHref($buildable->getURI());
if ($buildable->getIsManualBuildable()) {
$item->addIcon('fa-wrench grey', pht('Manual'));
}
$status_icon = $buildable->getStatusIcon();
$status_color = $buildable->getStatusColor();
$status_label = $buildable->getStatusDisplayName();
$item->setStatusIcon("{$status_icon} {$status_color}", $status_label);
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No buildables found.'));
return $result;
}
}
diff --git a/src/applications/harbormaster/typeahead/HarbormasterBuildDependencyDatasource.php b/src/applications/harbormaster/typeahead/HarbormasterBuildDependencyDatasource.php
index 08b0be774e..8453c56239 100644
--- a/src/applications/harbormaster/typeahead/HarbormasterBuildDependencyDatasource.php
+++ b/src/applications/harbormaster/typeahead/HarbormasterBuildDependencyDatasource.php
@@ -1,54 +1,54 @@
<?php
final class HarbormasterBuildDependencyDatasource
extends PhabricatorTypeaheadDatasource {
public function isBrowsable() {
// TODO: This should be browsable, but fixing it is involved.
return false;
}
public function getBrowseTitle() {
return pht('Browse Dependencies');
}
public function getPlaceholderText() {
return pht('Type another build step name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$plan_phid = $this->getParameter('planPHID');
$step_phid = $this->getParameter('stepPHID');
$steps = id(new HarbormasterBuildStepQuery())
->setViewer($viewer)
->withBuildPlanPHIDs(array($plan_phid))
->execute();
$steps = mpull($steps, null, 'getPHID');
if (count($steps) === 0) {
return array();
}
$results = array();
foreach ($steps as $phid => $step) {
if ($step->getPHID() === $step_phid) {
continue;
}
$results[] = id(new PhabricatorTypeaheadResult())
->setName($step->getName())
->setURI('/')
->setPHID($phid);
}
return $results;
}
}
diff --git a/src/applications/harbormaster/typeahead/HarbormasterBuildPlanDatasource.php b/src/applications/harbormaster/typeahead/HarbormasterBuildPlanDatasource.php
index cf5b815c57..ff831a74c5 100644
--- a/src/applications/harbormaster/typeahead/HarbormasterBuildPlanDatasource.php
+++ b/src/applications/harbormaster/typeahead/HarbormasterBuildPlanDatasource.php
@@ -1,44 +1,44 @@
<?php
final class HarbormasterBuildPlanDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Build Plans');
}
public function getPlaceholderText() {
return pht('Type a build plan name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
$query = id(new HarbormasterBuildPlanQuery())
->setOrder('name')
->withDatasourceQuery($raw_query);
$plans = $this->executeQuery($query);
foreach ($plans as $plan) {
$closed = null;
if ($plan->isDisabled()) {
$closed = pht('Disabled');
}
$results[] = id(new PhabricatorTypeaheadResult())
->setName($plan->getName())
->setClosed($closed)
->setPHID($plan->getPHID());
}
return $results;
}
}
diff --git a/src/applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php b/src/applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php
index 6cc11bd0c2..86c9da35e0 100644
--- a/src/applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php
+++ b/src/applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php
@@ -1,45 +1,45 @@
<?php
final class HarbormasterBuildStatusDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Choose Build Statuses');
}
public function getPlaceholderText() {
return pht('Type a build status name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHarbormasterApplication';
+ return PhabricatorHarbormasterApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
public function renderTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$status_map = HarbormasterBuildStatus::getBuildStatusMap();
foreach ($status_map as $value => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setIcon(HarbormasterBuildStatus::getBuildStatusIcon($value))
->setColor(HarbormasterBuildStatus::getBuildStatusColor($value))
->setPHID($value)
->setName($name)
->addAttribute(pht('Status'));
$results[$value] = $result;
}
return $results;
}
}
diff --git a/src/applications/herald/adapter/HeraldRuleAdapter.php b/src/applications/herald/adapter/HeraldRuleAdapter.php
index 8ed851a1a9..d5d1423ae7 100644
--- a/src/applications/herald/adapter/HeraldRuleAdapter.php
+++ b/src/applications/herald/adapter/HeraldRuleAdapter.php
@@ -1,74 +1,74 @@
<?php
final class HeraldRuleAdapter extends HeraldAdapter {
private $rule;
protected function newObject() {
return new HeraldRule();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to Herald rules being created or updated.');
}
public function isTestAdapterForObject($object) {
return ($object instanceof HeraldRule);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when another Herald rule is created or '.
'updated.');
}
protected function initializeNewAdapter() {
$this->rule = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setRule(HeraldRule $rule) {
$this->rule = $rule;
return $this;
}
public function getRule() {
return $this->rule;
}
public function setObject($object) {
$this->rule = $object;
return $this;
}
public function getObject() {
return $this->rule;
}
public function getAdapterContentName() {
return pht('Herald Rules');
}
public function getHeraldName() {
return $this->getRule()->getMonogram();
}
}
diff --git a/src/applications/herald/editor/HeraldRuleEditor.php b/src/applications/herald/editor/HeraldRuleEditor.php
index ea099cc6f3..01f42969f1 100644
--- a/src/applications/herald/editor/HeraldRuleEditor.php
+++ b/src/applications/herald/editor/HeraldRuleEditor.php
@@ -1,87 +1,87 @@
<?php
final class HeraldRuleEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Herald Rules');
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldRuleAdapter())
->setRule($object);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->getActingAsPHID();
if ($object->isPersonalRule()) {
$phids[] = $object->getAuthorPHID();
}
return $phids;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new HeraldRuleReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getName();
$subject = pht('%s: %s', $monogram, $name);
return id(new PhabricatorMetaMTAMail())
->setSubject($subject);
}
protected function getMailSubjectPrefix() {
return pht('[Herald]');
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('RULE DETAIL'),
PhabricatorEnv::getProductionURI($object->getURI()));
return $body;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/herald/editor/HeraldWebhookEditEngine.php b/src/applications/herald/editor/HeraldWebhookEditEngine.php
index 5bca0af542..527aafe110 100644
--- a/src/applications/herald/editor/HeraldWebhookEditEngine.php
+++ b/src/applications/herald/editor/HeraldWebhookEditEngine.php
@@ -1,105 +1,105 @@
<?php
final class HeraldWebhookEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'herald.webhook';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Webhooks');
}
public function getSummaryHeader() {
return pht('Edit Webhook Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit webhooks.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return HeraldWebhook::initializeNewWebhook($viewer);
}
protected function newObjectQuery() {
return new HeraldWebhookQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Webhook');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Webhook');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Webhook: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Webhook');
}
protected function getObjectCreateShortText() {
return pht('Create Webhook');
}
protected function getObjectName() {
return pht('Webhook');
}
protected function getEditorURI() {
return '/herald/webhook/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/herald/webhook/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
HeraldCreateWebhooksCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the webhook.'))
->setTransactionType(HeraldWebhookNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('uri')
->setLabel(pht('URI'))
->setDescription(pht('URI for the webhook.'))
->setTransactionType(HeraldWebhookURITransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getWebhookURI()),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setDescription(pht('Status mode for the webhook.'))
->setTransactionType(HeraldWebhookStatusTransaction::TRANSACTIONTYPE)
->setOptions(HeraldWebhook::getStatusDisplayNameMap())
->setValue($object->getStatus()),
);
}
}
diff --git a/src/applications/herald/editor/HeraldWebhookEditor.php b/src/applications/herald/editor/HeraldWebhookEditor.php
index 1f138e5028..4cbb57484b 100644
--- a/src/applications/herald/editor/HeraldWebhookEditor.php
+++ b/src/applications/herald/editor/HeraldWebhookEditor.php
@@ -1,31 +1,31 @@
<?php
final class HeraldWebhookEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Webhooks');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this webhook.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/herald/phid/HeraldRulePHIDType.php b/src/applications/herald/phid/HeraldRulePHIDType.php
index a70f89b406..767b242495 100644
--- a/src/applications/herald/phid/HeraldRulePHIDType.php
+++ b/src/applications/herald/phid/HeraldRulePHIDType.php
@@ -1,77 +1,77 @@
<?php
final class HeraldRulePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HRUL';
public function getTypeName() {
return pht('Herald Rule');
}
public function newObject() {
return new HeraldRule();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HeraldRuleQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$rule = $objects[$phid];
$monogram = $rule->getMonogram();
$name = $rule->getName();
$handle->setName($monogram);
$handle->setFullName("{$monogram} {$name}");
$handle->setURI("/{$monogram}");
if ($rule->getIsDisabled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^H\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new HeraldRuleQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/herald/phid/HeraldTranscriptPHIDType.php b/src/applications/herald/phid/HeraldTranscriptPHIDType.php
index 12625d0c1a..a05c293a44 100644
--- a/src/applications/herald/phid/HeraldTranscriptPHIDType.php
+++ b/src/applications/herald/phid/HeraldTranscriptPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class HeraldTranscriptPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HLXS';
public function getTypeName() {
return pht('Herald Transcript');
}
public function newObject() {
return new HeraldTranscript();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HeraldTranscriptQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$xscript = $objects[$phid];
$id = $xscript->getID();
$handle->setName(pht('Transcript %s', $id));
$handle->setURI("/herald/transcript/$id/");
}
}
}
diff --git a/src/applications/herald/phid/HeraldWebhookPHIDType.php b/src/applications/herald/phid/HeraldWebhookPHIDType.php
index bf16e22b1a..e88945b13d 100644
--- a/src/applications/herald/phid/HeraldWebhookPHIDType.php
+++ b/src/applications/herald/phid/HeraldWebhookPHIDType.php
@@ -1,49 +1,49 @@
<?php
final class HeraldWebhookPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HWBH';
public function getTypeName() {
return pht('Webhook');
}
public function newObject() {
return new HeraldWebhook();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HeraldWebhookQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$hook = $objects[$phid];
$name = $hook->getName();
$id = $hook->getID();
$handle
->setName($name)
->setURI($hook->getURI())
->setFullName(pht('Webhook %d %s', $id, $name));
if ($hook->isDisabled()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/herald/phid/HeraldWebhookRequestPHIDType.php b/src/applications/herald/phid/HeraldWebhookRequestPHIDType.php
index bcf5afb0d3..034bfa9b66 100644
--- a/src/applications/herald/phid/HeraldWebhookRequestPHIDType.php
+++ b/src/applications/herald/phid/HeraldWebhookRequestPHIDType.php
@@ -1,38 +1,38 @@
<?php
final class HeraldWebhookRequestPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'HWBR';
public function getTypeName() {
return pht('Webhook Request');
}
public function newObject() {
return new HeraldWebhook();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HeraldWebhookRequestQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$request = $objects[$phid];
$handle->setName(pht('Webhook Request %d', $request->getID()));
}
}
}
diff --git a/src/applications/herald/query/HeraldRuleQuery.php b/src/applications/herald/query/HeraldRuleQuery.php
index e104c44122..f5eedd8177 100644
--- a/src/applications/herald/query/HeraldRuleQuery.php
+++ b/src/applications/herald/query/HeraldRuleQuery.php
@@ -1,337 +1,337 @@
<?php
final class HeraldRuleQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $ruleTypes;
private $contentTypes;
private $disabled;
private $active;
private $datasourceQuery;
private $triggerObjectPHIDs;
private $affectedObjectPHIDs;
private $needConditionsAndActions;
private $needAppliedToPHIDs;
private $needValidateAuthors;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withRuleTypes(array $types) {
$this->ruleTypes = $types;
return $this;
}
public function withContentTypes(array $types) {
$this->contentTypes = $types;
return $this;
}
public function withDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function withActive($active) {
$this->active = $active;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function withTriggerObjectPHIDs(array $phids) {
$this->triggerObjectPHIDs = $phids;
return $this;
}
public function withAffectedObjectPHIDs(array $phids) {
$this->affectedObjectPHIDs = $phids;
return $this;
}
public function needConditionsAndActions($need) {
$this->needConditionsAndActions = $need;
return $this;
}
public function needAppliedToPHIDs(array $phids) {
$this->needAppliedToPHIDs = $phids;
return $this;
}
public function needValidateAuthors($need) {
$this->needValidateAuthors = $need;
return $this;
}
public function newResultObject() {
return new HeraldRule();
}
protected function willFilterPage(array $rules) {
$rule_ids = mpull($rules, 'getID');
// Filter out any rules that have invalid adapters, or have adapters the
// viewer isn't permitted to see or use (for example, Differential rules
// if the user can't use Differential or Differential is not installed).
$types = HeraldAdapter::getEnabledAdapterMap($this->getViewer());
foreach ($rules as $key => $rule) {
if (empty($types[$rule->getContentType()])) {
$this->didRejectResult($rule);
unset($rules[$key]);
}
}
if ($this->needValidateAuthors || ($this->active !== null)) {
$this->validateRuleAuthors($rules);
}
if ($this->active !== null) {
$need_active = (bool)$this->active;
foreach ($rules as $key => $rule) {
if ($rule->getIsDisabled()) {
$is_active = false;
} else if (!$rule->hasValidAuthor()) {
$is_active = false;
} else {
$is_active = true;
}
if ($is_active != $need_active) {
unset($rules[$key]);
}
}
}
if (!$rules) {
return array();
}
if ($this->needConditionsAndActions) {
$conditions = id(new HeraldCondition())->loadAllWhere(
'ruleID IN (%Ld)',
$rule_ids);
$conditions = mgroup($conditions, 'getRuleID');
$actions = id(new HeraldActionRecord())->loadAllWhere(
'ruleID IN (%Ld)',
$rule_ids);
$actions = mgroup($actions, 'getRuleID');
foreach ($rules as $rule) {
$rule->attachActions(idx($actions, $rule->getID(), array()));
$rule->attachConditions(idx($conditions, $rule->getID(), array()));
}
}
if ($this->needAppliedToPHIDs) {
$conn_r = id(new HeraldRule())->establishConnection('r');
$applied = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)',
HeraldRule::TABLE_RULE_APPLIED,
$rule_ids,
$this->needAppliedToPHIDs);
$map = array();
foreach ($applied as $row) {
$map[$row['ruleID']][$row['phid']] = true;
}
foreach ($rules as $rule) {
foreach ($this->needAppliedToPHIDs as $phid) {
$rule->setRuleApplied(
$phid,
isset($map[$rule->getID()][$phid]));
}
}
}
$object_phids = array();
foreach ($rules as $rule) {
if ($rule->isObjectRule()) {
$object_phids[] = $rule->getTriggerObjectPHID();
}
}
if ($object_phids) {
$objects = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
foreach ($rules as $key => $rule) {
if ($rule->isObjectRule()) {
$object = idx($objects, $rule->getTriggerObjectPHID());
if (!$object) {
unset($rules[$key]);
continue;
}
$rule->attachTriggerObject($object);
}
}
return $rules;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'rule.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'rule.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'rule.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->ruleTypes !== null) {
$where[] = qsprintf(
$conn,
'rule.ruleType IN (%Ls)',
$this->ruleTypes);
}
if ($this->contentTypes !== null) {
$where[] = qsprintf(
$conn,
'rule.contentType IN (%Ls)',
$this->contentTypes);
}
if ($this->disabled !== null) {
$where[] = qsprintf(
$conn,
'rule.isDisabled = %d',
(int)$this->disabled);
}
if ($this->active !== null) {
$where[] = qsprintf(
$conn,
'rule.isDisabled = %d',
(int)(!$this->active));
}
if ($this->datasourceQuery !== null) {
$where[] = qsprintf(
$conn,
'rule.name LIKE %>',
$this->datasourceQuery);
}
if ($this->triggerObjectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'rule.triggerObjectPHID IN (%Ls)',
$this->triggerObjectPHIDs);
}
if ($this->affectedObjectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'edge_affects.dst IN (%Ls)',
$this->affectedObjectPHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->affectedObjectPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T edge_affects ON rule.phid = edge_affects.src
AND edge_affects.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
HeraldRuleActionAffectsObjectEdgeType::EDGECONST);
}
return $joins;
}
private function validateRuleAuthors(array $rules) {
// "Global" and "Object" rules always have valid authors.
foreach ($rules as $key => $rule) {
if ($rule->isGlobalRule() || $rule->isObjectRule()) {
$rule->attachValidAuthor(true);
unset($rules[$key]);
continue;
}
}
if (!$rules) {
return;
}
// For personal rules, the author needs to exist and not be disabled.
$user_phids = mpull($rules, 'getAuthorPHID');
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withPHIDs($user_phids)
->execute();
$users = mpull($users, null, 'getPHID');
foreach ($rules as $key => $rule) {
$author_phid = $rule->getAuthorPHID();
if (empty($users[$author_phid])) {
$rule->attachValidAuthor(false);
continue;
}
if (!$users[$author_phid]->isUserActivated()) {
$rule->attachValidAuthor(false);
continue;
}
$rule->attachValidAuthor(true);
$rule->attachAuthor($users[$author_phid]);
}
}
public function getQueryApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
protected function getPrimaryTableAlias() {
return 'rule';
}
}
diff --git a/src/applications/herald/query/HeraldRuleSearchEngine.php b/src/applications/herald/query/HeraldRuleSearchEngine.php
index 95e3079717..b4e10035a3 100644
--- a/src/applications/herald/query/HeraldRuleSearchEngine.php
+++ b/src/applications/herald/query/HeraldRuleSearchEngine.php
@@ -1,172 +1,172 @@
<?php
final class HeraldRuleSearchEngine extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Herald Rules');
}
public function getApplicationClassName() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function newQuery() {
return id(new HeraldRuleQuery())
->needValidateAuthors(true);
}
protected function buildCustomSearchFields() {
$viewer = $this->requireViewer();
$rule_types = HeraldRuleTypeConfig::getRuleTypeMap();
$content_types = HeraldAdapter::getEnabledAdapterMap($viewer);
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors', 'authorPHID'))
->setDescription(
pht('Search for rules with given authors.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('ruleTypes')
->setAliases(array('ruleType'))
->setLabel(pht('Rule Type'))
->setDescription(
pht('Search for rules of given types.'))
->setOptions($rule_types),
id(new PhabricatorSearchCheckboxesField())
->setKey('contentTypes')
->setLabel(pht('Content Type'))
->setDescription(
pht('Search for rules affecting given types of content.'))
->setOptions($content_types),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Active Rules'))
->setKey('active')
->setOptions(
pht('(Show All)'),
pht('Show Only Active Rules'),
pht('Show Only Inactive Rules')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Disabled Rules'))
->setKey('disabled')
->setOptions(
pht('(Show All)'),
pht('Show Only Disabled Rules'),
pht('Show Only Enabled Rules')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Affected Objects'))
->setKey('affectedPHIDs')
->setAliases(array('affectedPHID')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['contentTypes']) {
$query->withContentTypes($map['contentTypes']);
}
if ($map['ruleTypes']) {
$query->withRuleTypes($map['ruleTypes']);
}
if ($map['disabled'] !== null) {
$query->withDisabled($map['disabled']);
}
if ($map['active'] !== null) {
$query->withActive($map['active']);
}
if ($map['affectedPHIDs']) {
$query->withAffectedObjectPHIDs($map['affectedPHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/herald/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query
->setParameter('active', true);
case 'authored':
return $query
->setParameter('authorPHIDs', array($viewer_phid))
->setParameter('disabled', false);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $rules,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($rules, 'HeraldRule');
$viewer = $this->requireViewer();
$list = id(new HeraldRuleListView())
->setViewer($viewer)
->setRules($rules)
->newObjectList();
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No rules found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create Herald Rule'))
->setHref('/herald/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('A flexible rules engine that can notify and act on '.
'other actions such as tasks, diffs, and commits.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/herald/query/HeraldTranscriptQuery.php b/src/applications/herald/query/HeraldTranscriptQuery.php
index 00a9dffeaf..6e9cf223b0 100644
--- a/src/applications/herald/query/HeraldTranscriptQuery.php
+++ b/src/applications/herald/query/HeraldTranscriptQuery.php
@@ -1,136 +1,136 @@
<?php
final class HeraldTranscriptQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $objectPHIDs;
private $needPartialRecords;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function needPartialRecords($need_partial) {
$this->needPartialRecords = $need_partial;
return $this;
}
protected function loadPage() {
$transcript = new HeraldTranscript();
$conn = $transcript->establishConnection('r');
// NOTE: Transcripts include a potentially enormous amount of serialized
// data, so we're loading only some of the fields here if the caller asked
// for partial records.
if ($this->needPartialRecords) {
$fields = array(
'id',
'phid',
'objectPHID',
'time',
'duration',
'dryRun',
'host',
);
$fields = qsprintf($conn, '%LC', $fields);
} else {
$fields = qsprintf($conn, '*');
}
$rows = queryfx_all(
$conn,
'SELECT %Q FROM %T t %Q %Q %Q',
$fields,
$transcript->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
$transcripts = $transcript->loadAllFromArray($rows);
if ($this->needPartialRecords) {
// Make sure nothing tries to write these; they aren't complete.
foreach ($transcripts as $transcript) {
$transcript->makeEphemeral();
}
}
return $transcripts;
}
protected function willFilterPage(array $transcripts) {
$phids = mpull($transcripts, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($phids)
->execute();
foreach ($transcripts as $key => $transcript) {
$object_phid = $transcript->getObjectPHID();
if (!$object_phid) {
$transcript->attachObject(null);
continue;
}
$object = idx($objects, $object_phid);
if (!$object) {
$this->didRejectResult($transcript);
unset($transcripts[$key]);
}
$transcript->attachObject($object);
}
return $transcripts;
}
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->objectPHIDs) {
$where[] = qsprintf(
$conn,
'objectPHID in (%Ls)',
$this->objectPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
}
diff --git a/src/applications/herald/query/HeraldTranscriptSearchEngine.php b/src/applications/herald/query/HeraldTranscriptSearchEngine.php
index e35620f0da..02e5b6b6e4 100644
--- a/src/applications/herald/query/HeraldTranscriptSearchEngine.php
+++ b/src/applications/herald/query/HeraldTranscriptSearchEngine.php
@@ -1,147 +1,147 @@
<?php
final class HeraldTranscriptSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Herald Transcripts');
}
public function getApplicationClassName() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$object_monograms = $request->getStrList('objectMonograms');
$saved->setParameter('objectMonograms', $object_monograms);
$ids = $request->getStrList('ids');
foreach ($ids as $key => $id) {
if (!$id || !is_numeric($id)) {
unset($ids[$key]);
} else {
$ids[$key] = $id;
}
}
$saved->setParameter('ids', $ids);
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new HeraldTranscriptQuery());
$object_monograms = $saved->getParameter('objectMonograms');
if ($object_monograms) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->requireViewer())
->withNames($object_monograms)
->execute();
$query->withObjectPHIDs(mpull($objects, 'getPHID'));
}
$ids = $saved->getParameter('ids');
if ($ids) {
$query->withIDs($ids);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$object_monograms = $saved->getParameter('objectMonograms', array());
$ids = $saved->getParameter('ids', array());
$form
->appendChild(
id(new AphrontFormTextControl())
->setName('objectMonograms')
->setLabel(pht('Object Monograms'))
->setValue(implode(', ', $object_monograms)))
->appendChild(
id(new AphrontFormTextControl())
->setName('ids')
->setLabel(pht('Transcript IDs'))
->setValue(implode(', ', $ids)));
}
protected function getURI($path) {
return '/herald/transcript/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Transcripts'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $transcripts,
PhabricatorSavedQuery $query) {
return mpull($transcripts, 'getObjectPHID');
}
protected function renderResultList(
array $transcripts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($transcripts, 'HeraldTranscript');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($transcripts as $xscript) {
$view_href = phutil_tag(
'a',
array(
'href' => '/herald/transcript/'.$xscript->getID().'/',
),
pht('View Full Transcript'));
$item = new PHUIObjectItemView();
$item->setObjectName($xscript->getID());
$item->setHeader($view_href);
if ($xscript->getDryRun()) {
$item->addAttribute(pht('Dry Run'));
}
$item->addAttribute($handles[$xscript->getObjectPHID()]->renderLink());
$item->addAttribute(
pht('%s ms', new PhutilNumber((int)(1000 * $xscript->getDuration()))));
$item->addIcon(
'none',
phabricator_datetime($xscript->getTime(), $viewer));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No transcripts found.'));
return $result;
}
}
diff --git a/src/applications/herald/query/HeraldWebhookQuery.php b/src/applications/herald/query/HeraldWebhookQuery.php
index 77307a71e6..fff20f7e6c 100644
--- a/src/applications/herald/query/HeraldWebhookQuery.php
+++ b/src/applications/herald/query/HeraldWebhookQuery.php
@@ -1,60 +1,60 @@
<?php
final class HeraldWebhookQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new HeraldWebhook();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
}
diff --git a/src/applications/herald/query/HeraldWebhookRequestQuery.php b/src/applications/herald/query/HeraldWebhookRequestQuery.php
index f0a61a2dc5..5c0e94cedc 100644
--- a/src/applications/herald/query/HeraldWebhookRequestQuery.php
+++ b/src/applications/herald/query/HeraldWebhookRequestQuery.php
@@ -1,122 +1,122 @@
<?php
final class HeraldWebhookRequestQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $webhookPHIDs;
private $lastRequestEpochMin;
private $lastRequestEpochMax;
private $lastRequestResults;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withWebhookPHIDs(array $phids) {
$this->webhookPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new HeraldWebhookRequest();
}
public function withLastRequestEpochBetween($epoch_min, $epoch_max) {
$this->lastRequestEpochMin = $epoch_min;
$this->lastRequestEpochMax = $epoch_max;
return $this;
}
public function withLastRequestResults(array $results) {
$this->lastRequestResults = $results;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->webhookPHIDs !== null) {
$where[] = qsprintf(
$conn,
'webhookPHID IN (%Ls)',
$this->webhookPHIDs);
}
if ($this->lastRequestEpochMin !== null) {
$where[] = qsprintf(
$conn,
'lastRequestEpoch >= %d',
$this->lastRequestEpochMin);
}
if ($this->lastRequestEpochMax !== null) {
$where[] = qsprintf(
$conn,
'lastRequestEpoch <= %d',
$this->lastRequestEpochMax);
}
if ($this->lastRequestResults !== null) {
$where[] = qsprintf(
$conn,
'lastRequestResult IN (%Ls)',
$this->lastRequestResults);
}
return $where;
}
protected function willFilterPage(array $requests) {
$hook_phids = mpull($requests, 'getWebhookPHID');
$hooks = id(new HeraldWebhookQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($hook_phids)
->execute();
$hooks = mpull($hooks, null, 'getPHID');
foreach ($requests as $key => $request) {
$hook_phid = $request->getWebhookPHID();
$hook = idx($hooks, $hook_phid);
if (!$hook) {
unset($requests[$key]);
$this->didRejectResult($request);
continue;
}
$request->attachWebhook($hook);
}
return $requests;
}
public function getQueryApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
}
diff --git a/src/applications/herald/query/HeraldWebhookSearchEngine.php b/src/applications/herald/query/HeraldWebhookSearchEngine.php
index 84997b60b1..ba898f4434 100644
--- a/src/applications/herald/query/HeraldWebhookSearchEngine.php
+++ b/src/applications/herald/query/HeraldWebhookSearchEngine.php
@@ -1,102 +1,102 @@
<?php
final class HeraldWebhookSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Webhooks');
}
public function getApplicationClassName() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function newQuery() {
return new HeraldWebhookQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setDescription(
pht('Search for archived or active pastes.'))
->setOptions(HeraldWebhook::getStatusDisplayNameMap()),
);
}
protected function getURI($path) {
return '/herald/webhook/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query->setParameter(
'statuses',
array(
HeraldWebhook::HOOKSTATUS_FIREHOSE,
HeraldWebhook::HOOKSTATUS_ENABLED,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $hooks,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($hooks, 'HeraldWebhook');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setViewer($viewer);
foreach ($hooks as $hook) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Webhook %d', $hook->getID()))
->setHeader($hook->getName())
->setHref($hook->getURI())
->addAttribute($hook->getWebhookURI());
$item->addIcon($hook->getStatusIcon(), $hook->getStatusDisplayName());
if ($hook->isDisabled()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No webhooks found.'));
}
}
diff --git a/src/applications/herald/typeahead/HeraldAdapterDatasource.php b/src/applications/herald/typeahead/HeraldAdapterDatasource.php
index 1fffd1bb6b..b0371b01a4 100644
--- a/src/applications/herald/typeahead/HeraldAdapterDatasource.php
+++ b/src/applications/herald/typeahead/HeraldAdapterDatasource.php
@@ -1,45 +1,45 @@
<?php
final class HeraldAdapterDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Herald Adapters');
}
public function getPlaceholderText() {
return pht('Type an adapter name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$adapters = HeraldAdapter::getAllAdapters();
foreach ($adapters as $adapter) {
$value = $adapter->getAdapterContentType();
$name = $adapter->getAdapterContentName();
$result = id(new PhabricatorTypeaheadResult())
->setPHID($value)
->setName($name);
$results[$value] = $result;
}
return $results;
}
}
diff --git a/src/applications/herald/typeahead/HeraldRuleDatasource.php b/src/applications/herald/typeahead/HeraldRuleDatasource.php
index 6b73bc0ab6..20cb0cf437 100644
--- a/src/applications/herald/typeahead/HeraldRuleDatasource.php
+++ b/src/applications/herald/typeahead/HeraldRuleDatasource.php
@@ -1,57 +1,57 @@
<?php
final class HeraldRuleDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a Herald rule name...');
}
public function getBrowseTitle() {
return pht('Browse Herald Rules');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$query = id(new HeraldRuleQuery())
->setViewer($viewer);
if (($raw_query !== null) && preg_match('/^[hH]\d+\z/', $raw_query)) {
$id = trim($raw_query, 'hH');
$id = (int)$id;
$query->withIDs(array($id));
} else {
$query->withDatasourceQuery($raw_query);
}
$rules = $query->execute();
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($rules, 'getPHID'))
->execute();
$results = array();
foreach ($rules as $rule) {
$handle = $handles[$rule->getPHID()];
$result = id(new PhabricatorTypeaheadResult())
->setName($handle->getFullName())
->setPHID($handle->getPHID());
if ($rule->getIsDisabled()) {
$result->setClosed(pht('Archived'));
}
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/herald/typeahead/HeraldRuleTypeDatasource.php b/src/applications/herald/typeahead/HeraldRuleTypeDatasource.php
index 8dfa7d0f6a..2bd81ff4a4 100644
--- a/src/applications/herald/typeahead/HeraldRuleTypeDatasource.php
+++ b/src/applications/herald/typeahead/HeraldRuleTypeDatasource.php
@@ -1,42 +1,42 @@
<?php
final class HeraldRuleTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Rule Types');
}
public function getPlaceholderText() {
return pht('Type a rule type...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$type_map = HeraldRuleTypeConfig::getRuleTypeMap();
foreach ($type_map as $type => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setPHID($type)
->setName($name);
$results[$type] = $result;
}
return $results;
}
}
diff --git a/src/applications/herald/typeahead/HeraldWebhookDatasource.php b/src/applications/herald/typeahead/HeraldWebhookDatasource.php
index a66431d515..f35dea6d30 100644
--- a/src/applications/herald/typeahead/HeraldWebhookDatasource.php
+++ b/src/applications/herald/typeahead/HeraldWebhookDatasource.php
@@ -1,48 +1,48 @@
<?php
final class HeraldWebhookDatasource
extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a webhook name...');
}
public function getBrowseTitle() {
return pht('Browse Webhooks');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorHeraldApplication';
+ return PhabricatorHeraldApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$hooks = id(new HeraldWebhookQuery())
->setViewer($viewer)
->execute();
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($hooks, 'getPHID'))
->execute();
$results = array();
foreach ($hooks as $hook) {
$handle = $handles[$hook->getPHID()];
$result = id(new PhabricatorTypeaheadResult())
->setName($handle->getFullName())
->setPHID($handle->getPHID());
if ($hook->isDisabled()) {
$result->setClosed(pht('Disabled'));
}
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/legalpad/editor/LegalpadDocumentEditEngine.php b/src/applications/legalpad/editor/LegalpadDocumentEditEngine.php
index fb3f54275a..e9810fad84 100644
--- a/src/applications/legalpad/editor/LegalpadDocumentEditEngine.php
+++ b/src/applications/legalpad/editor/LegalpadDocumentEditEngine.php
@@ -1,169 +1,169 @@
<?php
final class LegalpadDocumentEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'legalpad.document';
public function getEngineName() {
return pht('Legalpad');
}
public function getEngineApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Legalpad Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing documents in Legalpad.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$document = LegalpadDocument::initializeNewDocument($viewer);
$body = id(new LegalpadDocumentBody())
->setCreatorPHID($viewer->getPHID());
$document->attachDocumentBody($body);
$document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID);
return $document;
}
protected function newObjectQuery() {
return id(new LegalpadDocumentQuery())
->needDocumentBodies(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Document');
}
protected function getObjectEditTitleText($object) {
$body = $object->getDocumentBody();
$title = $body->getTitle();
return pht('Edit Document: %s', $title);
}
protected function getObjectEditShortText($object) {
$body = $object->getDocumentBody();
return $body->getTitle();
}
protected function getObjectCreateShortText() {
return pht('Create Document');
}
protected function getObjectName() {
return pht('Document');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return $this->getApplication()->getApplicationURI('view/'.$id.'/');
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
LegalpadCreateDocumentsCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$body = $object->getDocumentBody();
$document_body = $body->getText();
$is_create = $this->getIsCreate();
$is_admin = $viewer->getIsAdmin();
$fields = array();
$fields[] =
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
->setDescription(pht('Document Title.'))
->setConduitTypeDescription(pht('New document title.'))
->setValue($object->getTitle())
->setIsRequired(true)
->setTransactionType(
LegalpadDocumentTitleTransaction::TRANSACTIONTYPE);
if ($is_create) {
$fields[] =
id(new PhabricatorSelectEditField())
->setKey('signatureType')
->setLabel(pht('Who Should Sign?'))
->setDescription(pht('Type of signature required'))
->setConduitTypeDescription(pht('New document signature type.'))
->setValue($object->getSignatureType())
->setOptions(LegalpadDocument::getSignatureTypeMap())
->setTransactionType(
LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE);
$show_require = true;
} else {
$fields[] = id(new PhabricatorStaticEditField())
->setLabel(pht('Who Should Sign?'))
->setValue($object->getSignatureTypeName());
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
$show_require = $object->getSignatureType() == $individual;
}
if ($show_require && $is_admin) {
$fields[] =
id(new PhabricatorBoolEditField())
->setKey('requireSignature')
->setOptions(
pht('No Signature Required'),
pht('Signature Required to Log In'))
->setAsCheckbox(true)
->setTransactionType(
LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE)
->setDescription(pht('Marks this document as required signing.'))
->setConduitDescription(
pht('Marks this document as required signing.'))
->setValue($object->getRequireSignature());
}
$fields[] =
id(new PhabricatorRemarkupEditField())
->setKey('preamble')
->setLabel(pht('Preamble'))
->setDescription(pht('The preamble of the document.'))
->setConduitTypeDescription(pht('New document preamble.'))
->setValue($object->getPreamble())
->setTransactionType(
LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE);
$fields[] =
id(new PhabricatorRemarkupEditField())
->setKey('text')
->setLabel(pht('Document Body'))
->setDescription(pht('The body of text of the document.'))
->setConduitTypeDescription(pht('New document body.'))
->setValue($document_body)
->setIsRequired(true)
->setTransactionType(
LegalpadDocumentTextTransaction::TRANSACTIONTYPE);
return $fields;
}
}
diff --git a/src/applications/legalpad/editor/LegalpadDocumentEditor.php b/src/applications/legalpad/editor/LegalpadDocumentEditor.php
index 90f50564de..95ec232f09 100644
--- a/src/applications/legalpad/editor/LegalpadDocumentEditor.php
+++ b/src/applications/legalpad/editor/LegalpadDocumentEditor.php
@@ -1,183 +1,183 @@
<?php
final class LegalpadDocumentEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Legalpad Documents');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this document.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$is_contribution = false;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE:
case LegalpadDocumentTextTransaction::TRANSACTIONTYPE:
$is_contribution = true;
break;
}
}
if ($is_contribution) {
$text = $object->getDocumentBody()->getText();
$title = $object->getDocumentBody()->getTitle();
$object->setVersions($object->getVersions() + 1);
$body = new LegalpadDocumentBody();
$body->setCreatorPHID($this->getActingAsPHID());
$body->setText($text);
$body->setTitle($title);
$body->setVersion($object->getVersions());
$body->setDocumentPHID($object->getPHID());
$body->save();
$object->setDocumentBodyPHID($body->getPHID());
$type = PhabricatorContributedToObjectEdgeType::EDGECONST;
id(new PhabricatorEdgeEditor())
->addEdge($this->getActingAsPHID(), $type, $object->getPHID())
->save();
$type = PhabricatorObjectHasContributorEdgeType::EDGECONST;
$contributors = PhabricatorEdgeQuery::loadDestinationPHIDs(
$object->getPHID(),
$type);
$object->setRecentContributorPHIDs(array_slice($contributors, 0, 3));
$object->setContributorCount(count($contributors));
$object->save();
}
return $xactions;
}
protected function validateAllTransactions(PhabricatorLiskDAO $object,
array $xactions) {
$errors = array();
$is_required = (bool)$object->getRequireSignature();
$document_type = $object->getSignatureType();
$individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE:
$is_required = (bool)$xaction->getNewValue();
break;
case LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE:
$document_type = $xaction->getNewValue();
break;
}
}
if ($is_required && ($document_type != $individual)) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE,
pht('Invalid'),
pht('Only documents with signature type "individual" may '.
'require signing to log in.'),
null);
}
return $errors;
}
/* -( Sending Mail )------------------------------------------------------- */
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new LegalpadReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$title = $object->getDocumentBody()->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject("L{$id}: {$title}");
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getCreatorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function shouldImplyCC(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case LegalpadDocumentTextTransaction::TRANSACTIONTYPE:
case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE:
case LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE:
case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE:
return true;
}
return parent::shouldImplyCC($object, $xaction);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('DOCUMENT DETAIL'),
PhabricatorEnv::getProductionURI('/legalpad/view/'.$object->getID().'/'));
return $body;
}
protected function getMailSubjectPrefix() {
return pht('[Legalpad]');
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return false;
}
protected function supportsSearch() {
return false;
}
}
diff --git a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php
index 39c744f271..9cd7da1105 100644
--- a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php
+++ b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php
@@ -1,74 +1,74 @@
<?php
final class PhabricatorLegalpadDocumentPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'LEGD';
public function getTypeName() {
return pht('Legalpad Document');
}
public function getTypeIcon() {
return 'fa-file-text-o';
}
public function newObject() {
return new LegalpadDocument();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new LegalpadDocumentQuery())
->withPHIDs($phids)
->needDocumentBodies(true);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$document = $objects[$phid];
$name = $document->getDocumentBody()->getTitle();
$handle->setName($document->getMonogram().' '.$name);
$handle->setURI('/'.$document->getMonogram());
}
}
public function canLoadNamedObject($name) {
return preg_match('/^L\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new LegalpadDocumentQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentSignaturePHIDType.php b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentSignaturePHIDType.php
index 782dbf13aa..97d280865c 100644
--- a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentSignaturePHIDType.php
+++ b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentSignaturePHIDType.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorLegalpadDocumentSignaturePHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'LEGS';
public function getTypeName() {
return pht('Legalpad Signature');
}
public function getTypeIcon() {
return 'fa-file-text-o';
}
public function newObject() {
return new LegalpadDocumentSignature();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new LegalpadDocumentSignatureQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$sig = $objects[$phid];
$id = $sig->getID();
$handle->setName('Signature '.$id);
$signer_name = $sig->getSignerName();
$handle->setFullName("Signature {$id} by {$signer_name}");
$handle->setURI("/legalpad/signature/{$id}");
}
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentQuery.php b/src/applications/legalpad/query/LegalpadDocumentQuery.php
index 854a187fab..5e26ec31b1 100644
--- a/src/applications/legalpad/query/LegalpadDocumentQuery.php
+++ b/src/applications/legalpad/query/LegalpadDocumentQuery.php
@@ -1,269 +1,269 @@
<?php
final class LegalpadDocumentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $creatorPHIDs;
private $contributorPHIDs;
private $signerPHIDs;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $signatureRequired;
private $needDocumentBodies;
private $needContributors;
private $needSignatures;
private $needViewerSignatures;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
public function withContributorPHIDs(array $phids) {
$this->contributorPHIDs = $phids;
return $this;
}
public function withSignerPHIDs(array $phids) {
$this->signerPHIDs = $phids;
return $this;
}
public function withSignatureRequired($bool) {
$this->signatureRequired = $bool;
return $this;
}
public function needDocumentBodies($need_bodies) {
$this->needDocumentBodies = $need_bodies;
return $this;
}
public function needContributors($need_contributors) {
$this->needContributors = $need_contributors;
return $this;
}
public function needSignatures($need_signatures) {
$this->needSignatures = $need_signatures;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function needViewerSignatures($need) {
$this->needViewerSignatures = $need;
return $this;
}
public function newResultObject() {
return new LegalpadDocument();
}
protected function willFilterPage(array $documents) {
if ($this->needDocumentBodies) {
$documents = $this->loadDocumentBodies($documents);
}
if ($this->needContributors) {
$documents = $this->loadContributors($documents);
}
if ($this->needSignatures) {
$documents = $this->loadSignatures($documents);
}
if ($this->needViewerSignatures) {
if ($documents) {
if ($this->getViewer()->getPHID()) {
$signatures = id(new LegalpadDocumentSignatureQuery())
->setViewer($this->getViewer())
->withSignerPHIDs(array($this->getViewer()->getPHID()))
->withDocumentPHIDs(mpull($documents, 'getPHID'))
->execute();
$signatures = mpull($signatures, null, 'getDocumentPHID');
} else {
$signatures = array();
}
foreach ($documents as $document) {
$signature = idx($signatures, $document->getPHID());
$document->attachUserSignature(
$this->getViewer()->getPHID(),
$signature);
}
}
}
return $documents;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->contributorPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN edge contributor ON contributor.src = d.phid
AND contributor.type = %d',
PhabricatorObjectHasContributorEdgeType::EDGECONST);
}
if ($this->signerPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T signer ON signer.documentPHID = d.phid
AND signer.signerPHID IN (%Ls)',
id(new LegalpadDocumentSignature())->getTableName(),
$this->signerPHIDs);
}
return $joins;
}
protected function shouldGroupQueryResultRows() {
if ($this->contributorPHIDs) {
return true;
}
if ($this->signerPHIDs) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'd.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'd.phid IN (%Ls)',
$this->phids);
}
if ($this->creatorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'd.creatorPHID IN (%Ls)',
$this->creatorPHIDs);
}
if ($this->dateCreatedAfter !== null) {
$where[] = qsprintf(
$conn,
'd.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore !== null) {
$where[] = qsprintf(
$conn,
'd.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->contributorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'contributor.dst IN (%Ls)',
$this->contributorPHIDs);
}
if ($this->signatureRequired !== null) {
$where[] = qsprintf(
$conn,
'd.requireSignature = %d',
$this->signatureRequired);
}
return $where;
}
private function loadDocumentBodies(array $documents) {
$body_phids = mpull($documents, 'getDocumentBodyPHID');
$bodies = id(new LegalpadDocumentBody())->loadAllWhere(
'phid IN (%Ls)',
$body_phids);
$bodies = mpull($bodies, null, 'getPHID');
foreach ($documents as $document) {
$body = idx($bodies, $document->getDocumentBodyPHID());
$document->attachDocumentBody($body);
}
return $documents;
}
private function loadContributors(array $documents) {
$document_map = mpull($documents, null, 'getPHID');
$edge_type = PhabricatorObjectHasContributorEdgeType::EDGECONST;
$contributor_data = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($document_map))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($document_map as $document_phid => $document) {
$data = $contributor_data[$document_phid];
$contributors = array_keys(idx($data, $edge_type, array()));
$document->attachContributors($contributors);
}
return $documents;
}
private function loadSignatures(array $documents) {
$document_map = mpull($documents, null, 'getPHID');
$signatures = id(new LegalpadDocumentSignatureQuery())
->setViewer($this->getViewer())
->withDocumentPHIDs(array_keys($document_map))
->execute();
$signatures = mgroup($signatures, 'getDocumentPHID');
foreach ($documents as $document) {
$sigs = idx($signatures, $document->getPHID(), array());
$document->attachSignatures($sigs);
}
return $documents;
}
public function getQueryApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
protected function getPrimaryTableAlias() {
return 'd';
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentSearchEngine.php b/src/applications/legalpad/query/LegalpadDocumentSearchEngine.php
index 591174be57..cf168451a4 100644
--- a/src/applications/legalpad/query/LegalpadDocumentSearchEngine.php
+++ b/src/applications/legalpad/query/LegalpadDocumentSearchEngine.php
@@ -1,194 +1,194 @@
<?php
final class LegalpadDocumentSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Legalpad Documents');
}
public function getApplicationClassName() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
public function newQuery() {
return id(new LegalpadDocumentQuery())
->needViewerSignatures(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Signed By'))
->setKey('signerPHIDs')
->setAliases(array('signer', 'signers', 'signerPHID'))
->setDescription(
pht('Search for documents signed by given users.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Creators'))
->setKey('creatorPHIDs')
->setAliases(array('creator', 'creators', 'creatorPHID'))
->setDescription(
pht('Search for documents with given creators.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Contributors'))
->setKey('contributorPHIDs')
->setAliases(array('contributor', 'contributors', 'contributorPHID'))
->setDescription(
pht('Search for documents with given contributors.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['signerPHIDs']) {
$query->withSignerPHIDs($map['signerPHIDs']);
}
if ($map['contributorPHIDs']) {
$query->withContributorPHIDs($map['contributorPHIDs']);
}
if ($map['creatorPHIDs']) {
$query->withCreatorPHIDs($map['creatorPHIDs']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedAfter($map['createdStart']);
}
return $query;
}
protected function getURI($path) {
return '/legalpad/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['signed'] = pht('Signed Documents');
}
$names['all'] = pht('All Documents');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'signed':
return $query->setParameter('signerPHIDs', array($viewer->getPHID()));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $documents,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($documents, 'LegalpadDocument');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($documents as $document) {
$last_updated = phabricator_date($document->getDateModified(), $viewer);
$title = $document->getTitle();
$item = id(new PHUIObjectItemView())
->setObjectName($document->getMonogram())
->setHeader($title)
->setHref('/'.$document->getMonogram())
->setObject($document);
$no_signatures = LegalpadDocument::SIGNATURE_TYPE_NONE;
if ($document->getSignatureType() == $no_signatures) {
$item->addIcon('none', pht('Not Signable'));
} else {
$type_name = $document->getSignatureTypeName();
$type_icon = $document->getSignatureTypeIcon();
$item->addIcon($type_icon, $type_name);
if ($viewer->getPHID()) {
$signature = $document->getUserSignature($viewer->getPHID());
} else {
$signature = null;
}
if ($signature) {
$item->addAttribute(
array(
id(new PHUIIconView())->setIcon('fa-check-square-o', 'green'),
' ',
pht(
'Signed on %s',
phabricator_date($signature->getDateCreated(), $viewer)),
));
} else {
$item->addAttribute(
array(
id(new PHUIIconView())->setIcon('fa-square-o', 'grey'),
' ',
pht('Not Signed'),
));
}
}
$item->addIcon(
'fa-pencil grey',
pht('Version %d (%s)', $document->getVersions(), $last_updated));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No documents found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Document'))
->setHref('/legalpad/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Create documents and track signatures.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php b/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
index f8ee72c913..e8b57073e3 100644
--- a/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
+++ b/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
@@ -1,157 +1,157 @@
<?php
final class LegalpadDocumentSignatureQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $documentPHIDs;
private $signerPHIDs;
private $documentVersions;
private $secretKeys;
private $nameContains;
private $emailContains;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDocumentPHIDs(array $phids) {
$this->documentPHIDs = $phids;
return $this;
}
public function withSignerPHIDs(array $phids) {
$this->signerPHIDs = $phids;
return $this;
}
public function withDocumentVersions(array $versions) {
$this->documentVersions = $versions;
return $this;
}
public function withSecretKeys(array $keys) {
$this->secretKeys = $keys;
return $this;
}
public function withNameContains($text) {
$this->nameContains = $text;
return $this;
}
public function withEmailContains($text) {
$this->emailContains = $text;
return $this;
}
public function newResultObject() {
return new LegalpadDocumentSignature();
}
protected function loadPage() {
$table = $this->newResultObject();
$data = $this->loadStandardPageRows($table);
$signatures = $table->loadAllFromArray($data);
return $signatures;
}
protected function willFilterPage(array $signatures) {
$document_phids = mpull($signatures, 'getDocumentPHID');
$documents = id(new LegalpadDocumentQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($document_phids)
->execute();
$documents = mpull($documents, null, 'getPHID');
foreach ($signatures as $key => $signature) {
$document_phid = $signature->getDocumentPHID();
$document = idx($documents, $document_phid);
if ($document) {
$signature->attachDocument($document);
} else {
unset($signatures[$key]);
}
}
return $signatures;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
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->documentPHIDs !== null) {
$where[] = qsprintf(
$conn,
'documentPHID IN (%Ls)',
$this->documentPHIDs);
}
if ($this->signerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'signerPHID IN (%Ls)',
$this->signerPHIDs);
}
if ($this->documentVersions !== null) {
$where[] = qsprintf(
$conn,
'documentVersion IN (%Ld)',
$this->documentVersions);
}
if ($this->secretKeys !== null) {
$where[] = qsprintf(
$conn,
'secretKey IN (%Ls)',
$this->secretKeys);
}
if ($this->nameContains !== null) {
$where[] = qsprintf(
$conn,
'signerName LIKE %~',
$this->nameContains);
}
if ($this->emailContains !== null) {
$where[] = qsprintf(
$conn,
'signerEmail LIKE %~',
$this->emailContains);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php b/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php
index ac3e181889..d2c8149349 100644
--- a/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php
+++ b/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php
@@ -1,384 +1,384 @@
<?php
final class LegalpadDocumentSignatureSearchEngine
extends PhabricatorApplicationSearchEngine {
private $document;
public function newQuery() {
return new LegalpadDocumentSignatureQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Signed By'))
->setKey('signerPHIDs')
->setAliases(array('signer', 'signers', 'signerPHID'))
->setDescription(
pht('Search for signatures by given users.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Documents'))
->setKey('documentPHIDs')
->setAliases(array('document', 'documents', 'documentPHID'))
->setDescription(
pht('Search for signatures on the given documents')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('nameContains')
->setDescription(
pht('Search for signatures with a name containing the '.
'given string.')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Email Contains'))
->setKey('emailContains')
->setDescription(
pht('Search for signatures with an email containing the '.
'given string.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['signerPHIDs']) {
$query->withSignerPHIDs($map['signerPHIDs']);
}
if ($map['documentPHIDs']) {
$query->withDocumentPHIDs($map['documentPHIDs']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['nameContains']) {
$query->withNameContains($map['nameContains']);
}
if ($map['emailContains']) {
$query->withEmailContains($map['emailContains']);
}
return $query;
}
public function getResultTypeDescription() {
return pht('Legalpad Signatures');
}
public function getApplicationClassName() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
public function setDocument(LegalpadDocument $document) {
$this->document = $document;
return $this;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'signerPHIDs',
$this->readUsersFromRequest($request, 'signers'));
$saved->setParameter(
'documentPHIDs',
$this->readPHIDsFromRequest(
$request,
'documents',
array(
PhabricatorLegalpadDocumentPHIDType::TYPECONST,
)));
$saved->setParameter('nameContains', $request->getStr('nameContains'));
$saved->setParameter('emailContains', $request->getStr('emailContains'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new LegalpadDocumentSignatureQuery());
$signer_phids = $saved->getParameter('signerPHIDs', array());
if ($signer_phids) {
$query->withSignerPHIDs($signer_phids);
}
if ($this->document) {
$query->withDocumentPHIDs(array($this->document->getPHID()));
} else {
$document_phids = $saved->getParameter('documentPHIDs', array());
if ($document_phids) {
$query->withDocumentPHIDs($document_phids);
}
}
$name_contains = $saved->getParameter('nameContains');
if (phutil_nonempty_string($name_contains)) {
$query->withNameContains($name_contains);
}
$email_contains = $saved->getParameter('emailContains');
if (phutil_nonempty_string($email_contains)) {
$query->withEmailContains($email_contains);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$document_phids = $saved_query->getParameter('documentPHIDs', array());
$signer_phids = $saved_query->getParameter('signerPHIDs', array());
if (!$this->document) {
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new LegalpadDocumentDatasource())
->setName('documents')
->setLabel(pht('Documents'))
->setValue($document_phids));
}
$name_contains = $saved_query->getParameter('nameContains', '');
$email_contains = $saved_query->getParameter('emailContains', '');
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource())
->setName('signers')
->setLabel(pht('Signers'))
->setValue($signer_phids))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name Contains'))
->setName('nameContains')
->setValue($name_contains))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Email Contains'))
->setName('emailContains')
->setValue($email_contains));
}
protected function getURI($path) {
if ($this->document) {
return '/legalpad/signatures/'.$this->document->getID().'/'.$path;
} else {
return '/legalpad/signatures/'.$path;
}
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Signatures'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $signatures,
PhabricatorSavedQuery $query) {
return array_merge(
mpull($signatures, 'getSignerPHID'),
mpull($signatures, 'getDocumentPHID'));
}
protected function renderResultList(
array $signatures,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($signatures, 'LegalpadDocumentSignature');
$viewer = $this->requireViewer();
Javelin::initBehavior('phabricator-tooltips');
$sig_good = $this->renderIcon(
'fa-check',
null,
pht('Verified, Current'));
$sig_corp = $this->renderIcon(
'fa-building-o',
null,
pht('Verified, Corporate'));
$sig_old = $this->renderIcon(
'fa-clock-o',
'orange',
pht('Signed Older Version'));
$sig_unverified = $this->renderIcon(
'fa-envelope',
'red',
pht('Unverified Email'));
$sig_exemption = $this->renderIcon(
'fa-asterisk',
'indigo',
pht('Exemption'));
id(new PHUIIconView())
->setIcon('fa-envelope', 'red')
->addSigil('has-tooltip')
->setMetadata(array('tip' => pht('Unverified Email')));
$type_corporate = LegalpadDocument::SIGNATURE_TYPE_CORPORATION;
$rows = array();
foreach ($signatures as $signature) {
$name = $signature->getSignerName();
$email = $signature->getSignerEmail();
$document = $signature->getDocument();
if ($signature->getIsExemption()) {
$sig_icon = $sig_exemption;
} else if (!$signature->isVerified()) {
$sig_icon = $sig_unverified;
} else if ($signature->getDocumentVersion() != $document->getVersions()) {
$sig_icon = $sig_old;
} else if ($signature->getSignatureType() == $type_corporate) {
$sig_icon = $sig_corp;
} else {
$sig_icon = $sig_good;
}
$signature_href = $this->getApplicationURI(
'signature/'.$signature->getID().'/');
$sig_icon = javelin_tag(
'a',
array(
'href' => $signature_href,
'sigil' => 'workflow',
),
$sig_icon);
$signer_phid = $signature->getSignerPHID();
$rows[] = array(
$sig_icon,
$handles[$document->getPHID()]->renderLink(),
$signer_phid
? $handles[$signer_phid]->renderLink()
: phutil_tag('em', array(), pht('None')),
$name,
phutil_tag(
'a',
array(
'href' => 'mailto:'.$email,
),
$email),
phabricator_datetime($signature->getDateCreated(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setNoDataString(pht('No signatures match the query.'))
->setHeaders(
array(
'',
pht('Document'),
pht('Account'),
pht('Name'),
pht('Email'),
pht('Signed'),
))
->setColumnVisibility(
array(
true,
// Only show the "Document" column if we aren't scoped to a
// particular document.
!$this->document,
))
->setColumnClasses(
array(
'',
'',
'',
'',
'wide',
'right',
));
$button = null;
if ($this->document) {
$document_id = $this->document->getID();
$button = id(new PHUIButtonView())
->setText(pht('Add Exemption'))
->setTag('a')
->setHref($this->getApplicationURI('addsignature/'.$document_id.'/'))
->setWorkflow(true)
->setIcon('fa-pencil');
}
if (!$this->document) {
$table->setNotice(
pht('NOTE: You can only see your own signatures and signatures on '.
'documents you have permission to edit.'));
}
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
if ($button) {
$result->addAction($button);
}
return $result;
}
private function renderIcon($icon, $color, $title) {
Javelin::initBehavior('phabricator-tooltips');
return array(
id(new PHUIIconView())
->setIcon($icon, $color)
->addSigil('has-tooltip')
->setMetadata(array('tip' => $title)),
javelin_tag(
'span',
array(
'aural' => true,
),
$title),
);
}
}
diff --git a/src/applications/legalpad/typeahead/LegalpadDocumentDatasource.php b/src/applications/legalpad/typeahead/LegalpadDocumentDatasource.php
index a0117ee7b0..fccf078f36 100644
--- a/src/applications/legalpad/typeahead/LegalpadDocumentDatasource.php
+++ b/src/applications/legalpad/typeahead/LegalpadDocumentDatasource.php
@@ -1,40 +1,40 @@
<?php
final class LegalpadDocumentDatasource extends PhabricatorTypeaheadDatasource {
public function isBrowsable() {
// TODO: This should be made browsable.
return false;
}
public function getBrowseTitle() {
return pht('Browse Documents');
}
public function getPlaceholderText() {
return pht('Type a document name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorLegalpadApplication';
+ return PhabricatorLegalpadApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
$documents = id(new LegalpadDocumentQuery())
->setViewer($viewer)
->execute();
foreach ($documents as $document) {
$results[] = id(new PhabricatorTypeaheadResult())
->setPHID($document->getPHID())
->setName($document->getMonogram().' '.$document->getTitle());
}
return $results;
}
}
diff --git a/src/applications/macro/editor/PhabricatorMacroEditEngine.php b/src/applications/macro/editor/PhabricatorMacroEditEngine.php
index ff348c3163..d4a63f70ad 100644
--- a/src/applications/macro/editor/PhabricatorMacroEditEngine.php
+++ b/src/applications/macro/editor/PhabricatorMacroEditEngine.php
@@ -1,107 +1,107 @@
<?php
final class PhabricatorMacroEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'macro.image';
public function getEngineName() {
return pht('Macro Image');
}
public function getSummaryHeader() {
return pht('Configure Macro Image Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing of Macro images.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return PhabricatorFileImageMacro::initializeNewFileImageMacro($viewer);
}
protected function newObjectQuery() {
return new PhabricatorMacroQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Macro');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Macro %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Macro');
}
protected function getObjectName() {
return pht('Macro');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorMacroManageCapability::CAPABILITY);
}
protected function willConfigureFields($object, array $fields) {
if ($this->getIsCreate()) {
$subscribers_field = idx($fields,
PhabricatorSubscriptionsEditEngineExtension::FIELDKEY);
if ($subscribers_field) {
// By default, hide the subscribers field when creating a macro
// because it makes the workflow SO HARD and wastes SO MUCH TIME.
$subscribers_field->setIsHidden(true);
}
}
return $fields;
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Macro name.'))
->setConduitDescription(pht('Name of the macro.'))
->setConduitTypeDescription(pht('New macro name.'))
->setTransactionType(PhabricatorMacroNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorFileEditField())
->setKey('filePHID')
->setLabel(pht('Image File'))
->setDescription(pht('Image file to import.'))
->setTransactionType(PhabricatorMacroFileTransaction::TRANSACTIONTYPE)
->setConduitDescription(pht('File PHID to import.'))
->setConduitTypeDescription(pht('File PHID.'))
->setValue($object->getFilePHID()),
);
}
}
diff --git a/src/applications/macro/editor/PhabricatorMacroEditor.php b/src/applications/macro/editor/PhabricatorMacroEditor.php
index 91ed23a259..31db69921e 100644
--- a/src/applications/macro/editor/PhabricatorMacroEditor.php
+++ b/src/applications/macro/editor/PhabricatorMacroEditor.php
@@ -1,68 +1,68 @@
<?php
final class PhabricatorMacroEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Macros');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this macro.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorMacroReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
$name = 'Image Macro "'.$name.'"';
return id(new PhabricatorMetaMTAMail())
->setSubject($name);
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$this->requireActor()->getPHID(),
);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('MACRO DETAIL'),
PhabricatorEnv::getProductionURI('/macro/view/'.$object->getID().'/'));
return $body;
}
protected function getMailSubjectPrefix() {
return pht('[Macro]');
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
}
diff --git a/src/applications/macro/phid/PhabricatorMacroMacroPHIDType.php b/src/applications/macro/phid/PhabricatorMacroMacroPHIDType.php
index 19c7f5a1fc..a63b02f8ec 100644
--- a/src/applications/macro/phid/PhabricatorMacroMacroPHIDType.php
+++ b/src/applications/macro/phid/PhabricatorMacroMacroPHIDType.php
@@ -1,48 +1,48 @@
<?php
final class PhabricatorMacroMacroPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'MCRO';
public function getTypeName() {
return pht('Image Macro');
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function getTypeIcon() {
return 'fa-meh-o';
}
public function newObject() {
return new PhabricatorFileImageMacro();
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMacroQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$macro = $objects[$phid];
$id = $macro->getID();
$name = $macro->getName();
$handle->setName($name);
$handle->setFullName(pht('Image Macro "%s"', $name));
$handle->setURI("/macro/view/{$id}/");
}
}
}
diff --git a/src/applications/macro/query/PhabricatorMacroQuery.php b/src/applications/macro/query/PhabricatorMacroQuery.php
index 70e7f7e688..edfc97ef9d 100644
--- a/src/applications/macro/query/PhabricatorMacroQuery.php
+++ b/src/applications/macro/query/PhabricatorMacroQuery.php
@@ -1,264 +1,264 @@
<?php
final class PhabricatorMacroQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $names;
private $nameLike;
private $namePrefix;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $flagColor;
private $needFiles;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_ACTIVE = 'status-active';
const STATUS_DISABLED = 'status-disabled';
public static function getStatusOptions() {
return array(
self::STATUS_ACTIVE => pht('Active Macros'),
self::STATUS_DISABLED => pht('Disabled Macros'),
self::STATUS_ANY => pht('Active and Disabled Macros'),
);
}
public static function getFlagColorsOptions() {
$options = array(
'-1' => pht('(No Filtering)'),
'-2' => pht('(Marked With Any Flag)'),
);
foreach (PhabricatorFlagColor::getColorNameMap() as $color => $name) {
$options[$color] = $name;
}
return $options;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withNameLike($name) {
$this->nameLike = $name;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNamePrefix($prefix) {
$this->namePrefix = $prefix;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withFlagColor($flag_color) {
$this->flagColor = $flag_color;
return $this;
}
public function needFiles($need_files) {
$this->needFiles = $need_files;
return $this;
}
public function newResultObject() {
return new PhabricatorFileImageMacro();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'm.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'm.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'm.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if (($this->nameLike !== null) && strlen($this->nameLike)) {
$where[] = qsprintf(
$conn,
'm.name LIKE %~',
$this->nameLike);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'm.name IN (%Ls)',
$this->names);
}
if (($this->namePrefix !== null) && strlen($this->namePrefix)) {
$where[] = qsprintf(
$conn,
'm.name LIKE %>',
$this->namePrefix);
}
switch ($this->status) {
case self::STATUS_ACTIVE:
$where[] = qsprintf(
$conn,
'm.isDisabled = 0');
break;
case self::STATUS_DISABLED:
$where[] = qsprintf(
$conn,
'm.isDisabled = 1');
break;
case self::STATUS_ANY:
break;
default:
throw new Exception(pht("Unknown status '%s'!", $this->status));
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn,
'm.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn,
'm.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->flagColor != '-1' && $this->flagColor !== null) {
if ($this->flagColor == '-2') {
$flag_colors = array_keys(PhabricatorFlagColor::getColorNameMap());
} else {
$flag_colors = array($this->flagColor);
}
$flags = id(new PhabricatorFlagQuery())
->withOwnerPHIDs(array($this->getViewer()->getPHID()))
->withTypes(array(PhabricatorMacroMacroPHIDType::TYPECONST))
->withColors($flag_colors)
->setViewer($this->getViewer())
->execute();
if (empty($flags)) {
throw new PhabricatorEmptyQueryException(pht('No matching flags.'));
} else {
$where[] = qsprintf(
$conn,
'm.phid IN (%Ls)',
mpull($flags, 'getObjectPHID'));
}
}
return $where;
}
protected function didFilterPage(array $macros) {
if ($this->needFiles) {
$file_phids = mpull($macros, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($macros as $key => $macro) {
$file = idx($files, $macro->getFilePHID());
if (!$file) {
unset($macros[$key]);
continue;
}
$macro->attachFile($file);
}
}
return $macros;
}
protected function getPrimaryTableAlias() {
return 'm';
}
public function getQueryApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => 'm',
'column' => 'name',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
}
diff --git a/src/applications/macro/query/PhabricatorMacroSearchEngine.php b/src/applications/macro/query/PhabricatorMacroSearchEngine.php
index 7ef57a6a10..e61f52b8b8 100644
--- a/src/applications/macro/query/PhabricatorMacroSearchEngine.php
+++ b/src/applications/macro/query/PhabricatorMacroSearchEngine.php
@@ -1,211 +1,211 @@
<?php
final class PhabricatorMacroSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Macros');
}
public function getApplicationClassName() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function newQuery() {
return id(new PhabricatorMacroQuery())
->needFiles(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchSelectField())
->setLabel(pht('Status'))
->setKey('status')
->setOptions(PhabricatorMacroQuery::getStatusOptions()),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('nameLike'),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Exact Names'))
->setKey('names'),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Marked with Flag'))
->setKey('flagColor')
->setDefault('-1')
->setOptions(PhabricatorMacroQuery::getFlagColorsOptions()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function getDefaultFieldOrder() {
return array(
'...',
'createdStart',
'createdEnd',
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['status']) {
$query->withStatus($map['status']);
}
if ($map['names']) {
$query->withNames($map['names']);
}
if (strlen($map['nameLike'])) {
$query->withNameLike($map['nameLike']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedBefore($map['createdEnd']);
}
if ($map['flagColor'] !== null) {
$query->withFlagColor($map['flagColor']);
}
return $query;
}
protected function getURI($path) {
return '/macro/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active'),
'all' => pht('All'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter(
'status',
PhabricatorMacroQuery::STATUS_ACTIVE);
case 'all':
return $query->setParameter(
'status',
PhabricatorMacroQuery::STATUS_ANY);
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $macros,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($macros, 'PhabricatorFileImageMacro');
$viewer = $this->requireViewer();
$handles = $viewer->loadHandles(mpull($macros, 'getAuthorPHID'));
$xform = PhabricatorFileTransform::getTransformByKey(
PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
$pinboard = new PHUIPinboardView();
foreach ($macros as $macro) {
$file = $macro->getFile();
$item = id(new PHUIPinboardItemView())
->setUser($viewer)
->setObject($macro);
if ($file) {
$item->setImageURI($file->getURIForTransform($xform));
list($x, $y) = $xform->getTransformedDimensions($file);
$item->setImageSize($x, $y);
}
if ($macro->getDateCreated()) {
$datetime = phabricator_date($macro->getDateCreated(), $viewer);
$item->appendChild(
phutil_tag(
'div',
array(),
pht('Created on %s', $datetime)));
} else {
// Very old macros don't have a creation date. Rendering something
// keeps all the pins at the same height and avoids flow issues.
$item->appendChild(
phutil_tag(
'div',
array(),
pht('Created in ages long past')));
}
if ($macro->getAuthorPHID()) {
$author_handle = $handles[$macro->getAuthorPHID()];
$item->appendChild(
pht('Created by %s', $author_handle->renderLink()));
}
$item->setURI($this->getApplicationURI('/view/'.$macro->getID().'/'));
$item->setDisabled($macro->getisDisabled());
$item->setHeader($macro->getName());
$pinboard->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($pinboard);
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Macro'))
->setHref('/macro/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Create easy to remember shortcuts to images and memes.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/macro/typeahead/PhabricatorEmojiDatasource.php b/src/applications/macro/typeahead/PhabricatorEmojiDatasource.php
index a0f0bda981..f967a37acc 100644
--- a/src/applications/macro/typeahead/PhabricatorEmojiDatasource.php
+++ b/src/applications/macro/typeahead/PhabricatorEmojiDatasource.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorEmojiDatasource extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type an emoji name...');
}
public function getBrowseTitle() {
return pht('Browse Emojis');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$raw_query = $this->getRawQuery();
$data = id(new PhabricatorEmojiRemarkupRule())->markupEmojiJSON();
$emojis = phutil_json_decode($data);
$results = array();
foreach ($emojis as $shortname => $emoji) {
$display_name = $emoji.' '.$shortname;
$name = str_replace('_', ' ', $shortname);
$result = id(new PhabricatorTypeaheadResult())
->setPHID($shortname)
->setName($name)
->setDisplayname($display_name)
->setAutocomplete($emoji);
$results[$shortname] = $result;
}
return $results;
}
}
diff --git a/src/applications/macro/typeahead/PhabricatorMacroDatasource.php b/src/applications/macro/typeahead/PhabricatorMacroDatasource.php
index b7b7efd630..c62adb041a 100644
--- a/src/applications/macro/typeahead/PhabricatorMacroDatasource.php
+++ b/src/applications/macro/typeahead/PhabricatorMacroDatasource.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorMacroDatasource extends PhabricatorTypeaheadDatasource {
public function getPlaceholderText() {
return pht('Type a macro name...');
}
public function getBrowseTitle() {
return pht('Browse Macros');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorMacroApplication';
+ return PhabricatorMacroApplication::class;
}
public function loadResults() {
$raw_query = $this->getRawQuery();
$query = id(new PhabricatorMacroQuery())
->setOrder('name')
->withNamePrefix($raw_query);
$macros = $this->executeQuery($query);
$results = array();
foreach ($macros as $macro) {
$closed = null;
if ($macro->getIsDisabled()) {
$closed = pht('Disabled');
}
$results[] = id(new PhabricatorTypeaheadResult())
->setPHID($macro->getPHID())
->setClosed($closed)
->setName($macro->getName());
}
return $results;
}
}
diff --git a/src/applications/maniphest/editor/ManiphestEditEngine.php b/src/applications/maniphest/editor/ManiphestEditEngine.php
index fc3c48b205..46877168e7 100644
--- a/src/applications/maniphest/editor/ManiphestEditEngine.php
+++ b/src/applications/maniphest/editor/ManiphestEditEngine.php
@@ -1,549 +1,549 @@
<?php
final class ManiphestEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'maniphest.task';
public function getEngineName() {
return pht('Maniphest Tasks');
}
public function getSummaryHeader() {
return pht('Configure Maniphest Task Forms');
}
public function getSummaryText() {
return pht('Configure how users create and edit tasks.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function isDefaultQuickCreateEngine() {
return true;
}
public function getQuickCreateOrderVector() {
return id(new PhutilSortVector())->addInt(100);
}
protected function newEditableObject() {
return ManiphestTask::initializeNewTask($this->getViewer());
}
protected function newObjectQuery() {
return id(new ManiphestTaskQuery());
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Task');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Task: %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
protected function getObjectCreateShortText() {
return pht('Create Task');
}
protected function getObjectName() {
return pht('Task');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('task/edit/');
}
protected function getCommentViewHeaderText($object) {
return pht('Weigh In');
}
protected function getCommentViewButtonText($object) {
return pht('Set Sail for Adventure');
}
protected function getObjectViewURI($object) {
return '/'.$object->getMonogram();
}
protected function buildCustomEditFields($object) {
$status_map = $this->getTaskStatusMap($object);
$priority_map = $this->getTaskPriorityMap($object);
$alias_map = ManiphestTaskPriority::getTaskPriorityAliasMap();
if ($object->isClosed()) {
$default_status = ManiphestTaskStatus::getDefaultStatus();
} else {
$default_status = ManiphestTaskStatus::getDefaultClosedStatus();
}
if ($object->getOwnerPHID()) {
$owner_value = array($object->getOwnerPHID());
} else {
$owner_value = array($this->getViewer()->getPHID());
}
$column_documentation = pht(<<<EODOCS
You can use this transaction type to create a task into a particular workboard
column, or move an existing task between columns.
The transaction value can be specified in several forms. Some are simpler but
less powerful, while others are more complex and more powerful.
The simplest valid value is a single column PHID:
```lang=json
"PHID-PCOL-1111"
```
This will move the task into that column, or create the task into that column
if you are creating a new task. If the task is currently on the board, it will
be moved out of any exclusive columns. If the task is not currently on the
board, it will be added to the board.
You can also perform multiple moves at the same time by passing a list of
PHIDs:
```lang=json
["PHID-PCOL-2222", "PHID-PCOL-3333"]
```
This is equivalent to performing each move individually.
The most complex and most powerful form uses a dictionary to provide additional
information about the move, including an optional specific position within the
column.
The target column should be identified as `columnPHID`, and you may select a
position by passing either `beforePHIDs` or `afterPHIDs`, specifying the PHIDs
of tasks currently in the column that you want to move this task before or
after:
```lang=json
[
{
"columnPHID": "PHID-PCOL-4444",
"beforePHIDs": ["PHID-TASK-5555"]
}
]
```
When you specify multiple PHIDs, the task will be moved adjacent to the first
valid PHID found in either of the lists. This allows positional moves to
generally work as users expect even if the client view of the board has fallen
out of date and some of the nearby tasks have moved elsewhere.
EODOCS
);
$column_map = $this->getColumnMap($object);
$fields = array(
id(new PhabricatorHandlesEditField())
->setKey('parent')
->setLabel(pht('Parent Task'))
->setDescription(pht('Task to make this a subtask of.'))
->setConduitDescription(pht('Create as a subtask of another task.'))
->setConduitTypeDescription(pht('PHID of the parent task.'))
->setAliases(array('parentPHID'))
->setTransactionType(ManiphestTaskParentTransaction::TRANSACTIONTYPE)
->setHandleParameterType(new ManiphestTaskListHTTPParameterType())
->setSingleValue(null)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false),
id(new PhabricatorColumnsEditField())
->setKey('column')
->setLabel(pht('Column'))
->setDescription(pht('Create a task in a workboard column.'))
->setConduitDescription(
pht('Move a task to one or more workboard columns.'))
->setConduitTypeDescription(
pht('List of columns to move the task to.'))
->setConduitDocumentation($column_documentation)
->setAliases(array('columnPHID', 'columns', 'columnPHIDs'))
->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setCommentActionLabel(pht('Move on Workboard'))
->setCommentActionOrder(2000)
->setColumnMap($column_map),
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
->setBulkEditLabel(pht('Set title to'))
->setDescription(pht('Name of the task.'))
->setConduitDescription(pht('Rename the task.'))
->setConduitTypeDescription(pht('New task name.'))
->setTransactionType(ManiphestTaskTitleTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getTitle()),
id(new PhabricatorUsersEditField())
->setKey('owner')
->setAliases(array('ownerPHID', 'assign', 'assigned'))
->setLabel(pht('Assigned To'))
->setBulkEditLabel(pht('Assign to'))
->setDescription(pht('User who is responsible for the task.'))
->setConduitDescription(pht('Reassign the task.'))
->setConduitTypeDescription(
pht('New task owner, or `null` to unassign.'))
->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setIsNullable(true)
->setSingleValue($object->getOwnerPHID())
->setCommentActionLabel(pht('Assign / Claim'))
->setCommentActionValue($owner_value),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setBulkEditLabel(pht('Set status to'))
->setDescription(pht('Status of the task.'))
->setConduitDescription(pht('Change the task status.'))
->setConduitTypeDescription(pht('New task status constant.'))
->setTransactionType(ManiphestTaskStatusTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getStatus())
->setOptions($status_map)
->setCommentActionLabel(pht('Change Status'))
->setCommentActionValue($default_status),
id(new PhabricatorSelectEditField())
->setKey('priority')
->setLabel(pht('Priority'))
->setBulkEditLabel(pht('Set priority to'))
->setDescription(pht('Priority of the task.'))
->setConduitDescription(pht('Change the priority of the task.'))
->setConduitTypeDescription(pht('New task priority constant.'))
->setTransactionType(ManiphestTaskPriorityTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getPriorityKeyword())
->setOptions($priority_map)
->setOptionAliases($alias_map)
->setCommentActionLabel(pht('Change Priority')),
);
if (ManiphestTaskPoints::getIsEnabled()) {
$points_label = ManiphestTaskPoints::getPointsLabel();
$action_label = ManiphestTaskPoints::getPointsActionLabel();
$fields[] = id(new PhabricatorPointsEditField())
->setKey('points')
->setLabel($points_label)
->setBulkEditLabel($action_label)
->setDescription(pht('Point value of the task.'))
->setConduitDescription(pht('Change the task point value.'))
->setConduitTypeDescription(pht('New task point value.'))
->setTransactionType(ManiphestTaskPointsTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getPoints())
->setCommentActionLabel($action_label);
}
$fields[] = id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setBulkEditLabel(pht('Set description to'))
->setDescription(pht('Task description.'))
->setConduitDescription(pht('Update the task description.'))
->setConduitTypeDescription(pht('New task description.'))
->setTransactionType(ManiphestTaskDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription())
->setPreviewPanel(
id(new PHUIRemarkupPreviewPanel())
->setHeader(pht('Description Preview')));
$parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
$subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
$commit_type = ManiphestTaskHasCommitEdgeType::EDGECONST;
$src_phid = $object->getPHID();
if ($src_phid) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($src_phid))
->withEdgeTypes(
array(
$parent_type,
$subtask_type,
$commit_type,
));
$edge_query->execute();
$parent_phids = $edge_query->getDestinationPHIDs(
array($src_phid),
array($parent_type));
$subtask_phids = $edge_query->getDestinationPHIDs(
array($src_phid),
array($subtask_type));
$commit_phids = $edge_query->getDestinationPHIDs(
array($src_phid),
array($commit_type));
} else {
$parent_phids = array();
$subtask_phids = array();
$commit_phids = array();
}
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('parents')
->setLabel(pht('Parents'))
->setDescription(pht('Parent tasks.'))
->setConduitDescription(pht('Change the parents of this task.'))
->setConduitTypeDescription(pht('List of parent task PHIDs.'))
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $parent_type)
->setValue($parent_phids);
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('subtasks')
->setLabel(pht('Subtasks'))
->setDescription(pht('Subtasks.'))
->setConduitDescription(pht('Change the subtasks of this task.'))
->setConduitTypeDescription(pht('List of subtask PHIDs.'))
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $subtask_type)
->setValue($subtask_phids);
$fields[] = id(new PhabricatorHandlesEditField())
->setKey('commits')
->setLabel(pht('Commits'))
->setDescription(pht('Related commits.'))
->setConduitDescription(pht('Change the related commits for this task.'))
->setConduitTypeDescription(pht('List of related commit PHIDs.'))
->setUseEdgeTransactions(true)
->setIsFormField(false)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $commit_type)
->setValue($commit_phids);
return $fields;
}
private function getTaskStatusMap(ManiphestTask $task) {
$status_map = ManiphestTaskStatus::getTaskStatusMap();
$current_status = $task->getStatus();
// If the current status is something we don't recognize (maybe an older
// status which was deleted), put a dummy entry in the status map so that
// saving the form doesn't destroy any data by accident.
if (idx($status_map, $current_status) === null) {
$status_map[$current_status] = pht('<Unknown: %s>', $current_status);
}
$dup_status = ManiphestTaskStatus::getDuplicateStatus();
foreach ($status_map as $status => $status_name) {
// Always keep the task's current status.
if ($status == $current_status) {
continue;
}
// Don't allow tasks to be changed directly into "Closed, Duplicate"
// status. Instead, you have to merge them. See T4819.
if ($status == $dup_status) {
unset($status_map[$status]);
continue;
}
// Don't let new or existing tasks be moved into a disabled status.
if (ManiphestTaskStatus::isDisabledStatus($status)) {
unset($status_map[$status]);
continue;
}
}
return $status_map;
}
private function getTaskPriorityMap(ManiphestTask $task) {
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
$priority_keywords = ManiphestTaskPriority::getTaskPriorityKeywordsMap();
$current_priority = $task->getPriority();
$results = array();
foreach ($priority_map as $priority => $priority_name) {
$disabled = ManiphestTaskPriority::isDisabledPriority($priority);
if ($disabled && !($priority == $current_priority)) {
continue;
}
$keyword = head(idx($priority_keywords, $priority));
$results[$keyword] = $priority_name;
}
// If the current value isn't a legitimate one, put it in the dropdown
// anyway so saving the form doesn't cause any side effects.
if (idx($priority_map, $current_priority) === null) {
$results[ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD] = pht(
'<Unknown: %s>',
$current_priority);
}
return $results;
}
protected function newEditResponse(
AphrontRequest $request,
$object,
array $xactions) {
$response_type = $request->getStr('responseType');
$is_card = ($response_type === 'card');
if ($is_card) {
// Reload the task to make sure we pick up the final task state.
$viewer = $this->getViewer();
$task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($object->getID()))
->needSubscriberPHIDs(true)
->needProjectPHIDs(true)
->executeOne();
return $this->buildCardResponse($task);
}
return parent::newEditResponse($request, $object, $xactions);
}
private function buildCardResponse(ManiphestTask $task) {
$controller = $this->getController();
$request = $controller->getRequest();
$viewer = $request->getViewer();
$column_phid = $request->getStr('columnPHID');
$visible_phids = $request->getStrList('visiblePHIDs');
if (!$visible_phids) {
$visible_phids = array();
}
$column = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withPHIDs(array($column_phid))
->executeOne();
if (!$column) {
return new Aphront404Response();
}
$board_phid = $column->getProjectPHID();
$object_phid = $task->getPHID();
$order = $request->getStr('order');
if ($order) {
$ordering = PhabricatorProjectColumnOrder::getOrderByKey($order);
$ordering = id(clone $ordering)
->setViewer($viewer);
} else {
$ordering = null;
}
$engine = id(new PhabricatorBoardResponseEngine())
->setViewer($viewer)
->setBoardPHID($board_phid)
->setUpdatePHIDs(array($object_phid))
->setVisiblePHIDs($visible_phids);
if ($ordering) {
$engine->setOrdering($ordering);
}
return $engine->buildResponse();
}
private function getColumnMap(ManiphestTask $task) {
$phid = $task->getPHID();
if (!$phid) {
return array();
}
$board_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$phid,
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
if (!$board_phids) {
return array();
}
$viewer = $this->getViewer();
$layout_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->setBoardPHIDs($board_phids)
->setObjectPHIDs(array($task->getPHID()))
->executeLayout();
$map = array();
foreach ($board_phids as $board_phid) {
$in_columns = $layout_engine->getObjectColumns($board_phid, $phid);
$in_columns = mpull($in_columns, null, 'getPHID');
$all_columns = $layout_engine->getColumns($board_phid);
if (!$all_columns) {
// This could be a project with no workboard, or a project the viewer
// does not have permission to see.
continue;
}
$board = head($all_columns)->getProject();
$options = array();
foreach ($all_columns as $column) {
$name = $column->getDisplayName();
$is_hidden = $column->isHidden();
$is_selected = isset($in_columns[$column->getPHID()]);
// Don't show hidden, subproject or milestone columns in this map
// unless the object is currently in the column.
$skip_column = ($is_hidden || $column->getProxyPHID());
if ($skip_column) {
if (!$is_selected) {
continue;
}
}
if ($is_hidden) {
$name = pht('(%s)', $name);
}
if ($is_selected) {
$name = pht("\xE2\x97\x8F %s", $name);
} else {
$name = pht("\xE2\x97\x8B %s", $name);
}
$option = array(
'key' => $column->getPHID(),
'label' => $name,
'selected' => (bool)$is_selected,
);
$options[] = $option;
}
$map[] = array(
'label' => $board->getDisplayName(),
'options' => $options,
);
}
$map = isort($map, 'label');
$map = array_values($map);
return $map;
}
}
diff --git a/src/applications/maniphest/editor/ManiphestTransactionEditor.php b/src/applications/maniphest/editor/ManiphestTransactionEditor.php
index 01fc0af83d..a6a10b33ed 100644
--- a/src/applications/maniphest/editor/ManiphestTransactionEditor.php
+++ b/src/applications/maniphest/editor/ManiphestTransactionEditor.php
@@ -1,935 +1,935 @@
<?php
final class ManiphestTransactionEditor
extends PhabricatorApplicationTransactionEditor {
private $oldProjectPHIDs;
private $moreValidationErrors = array();
public function getEditorApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Maniphest Tasks');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COLUMNS;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this task.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return null;
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return $xaction->getNewValue();
}
}
protected function transactionHasEffect(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return (bool)$new;
}
return parent::transactionHasEffect($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
return;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_COLUMNS:
foreach ($xaction->getNewValue() as $move) {
$this->applyBoardMove($object, $move);
}
break;
}
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// When we change the status of a task, update tasks this tasks blocks
// with a message to the effect of "alincoln resolved blocking task Txxx."
$unblock_xaction = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
$unblock_xaction = $xaction;
break;
}
}
if ($unblock_xaction !== null) {
$blocked_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$object->getPHID(),
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);
if ($blocked_phids) {
// In theory we could apply these through policies, but that seems a
// little bit surprising. For now, use the actor's vision.
$blocked_tasks = id(new ManiphestTaskQuery())
->setViewer($this->getActor())
->withPHIDs($blocked_phids)
->needSubscriberPHIDs(true)
->needProjectPHIDs(true)
->execute();
$old = $unblock_xaction->getOldValue();
$new = $unblock_xaction->getNewValue();
foreach ($blocked_tasks as $blocked_task) {
$parent_xaction = id(new ManiphestTransaction())
->setTransactionType(
ManiphestTaskUnblockTransaction::TRANSACTIONTYPE)
->setOldValue(array($object->getPHID() => $old))
->setNewValue(array($object->getPHID() => $new));
if ($this->getIsNewObject()) {
$parent_xaction->setMetadataValue('blocker.new', true);
}
$this->newSubEditor()
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->applyTransactions($blocked_task, array($parent_xaction));
}
}
}
return $xactions;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Maniphest]');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
return 'maniphest-task-'.$object->getPHID();
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
if ($object->getOwnerPHID()) {
$phids[] = $object->getOwnerPHID();
}
$phids[] = $this->getActingAsPHID();
return $phids;
}
public function getMailTagsMap() {
return array(
ManiphestTransaction::MAILTAG_STATUS =>
pht("A task's status changes."),
ManiphestTransaction::MAILTAG_OWNER =>
pht("A task's owner changes."),
ManiphestTransaction::MAILTAG_PRIORITY =>
pht("A task's priority changes."),
ManiphestTransaction::MAILTAG_CC =>
pht("A task's subscribers change."),
ManiphestTransaction::MAILTAG_PROJECTS =>
pht("A task's associated projects change."),
ManiphestTransaction::MAILTAG_UNBLOCK =>
pht("One of a task's subtasks changes status."),
ManiphestTransaction::MAILTAG_COLUMN =>
pht('A task is moved between columns on a workboard.'),
ManiphestTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a task.'),
ManiphestTransaction::MAILTAG_OTHER =>
pht('Other task activity not listed above occurs.'),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ManiphestReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$title = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject("T{$id}: {$title}");
}
protected function getObjectLinkButtonLabelForMail(
PhabricatorLiskDAO $object) {
return pht('View Task');
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
if ($this->getIsNewObject()) {
$body->addRemarkupSection(
pht('TASK DESCRIPTION'),
$object->getDescription());
}
$body->addLinkSection(
pht('TASK DETAIL'),
$this->getObjectLinkButtonURIForMail($object));
$board_phids = array();
$type_columns = PhabricatorTransactions::TYPE_COLUMNS;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $type_columns) {
$moves = $xaction->getNewValue();
foreach ($moves as $move) {
$board_phids[] = $move['boardPHID'];
}
}
}
if ($board_phids) {
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->requireActor())
->withPHIDs($board_phids)
->execute();
foreach ($projects as $project) {
$body->addLinkSection(
pht('WORKBOARD'),
PhabricatorEnv::getProductionURI($project->getWorkboardURI()));
}
}
return $body;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldManiphestTaskAdapter())
->setTask($object);
}
protected function adjustObjectForPolicyChecks(
PhabricatorLiskDAO $object,
array $xactions) {
$copy = parent::adjustObjectForPolicyChecks($object, $xactions);
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
$copy->setOwnerPHID($xaction->getNewValue());
break;
default:
break;
}
}
return $copy;
}
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$errors = parent::validateAllTransactions($object, $xactions);
if ($this->moreValidationErrors) {
$errors = array_merge($errors, $this->moreValidationErrors);
}
foreach ($this->getLockValidationErrors($object, $xactions) as $error) {
$errors[] = $error;
}
return $errors;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$actor = $this->getActor();
$actor_phid = $actor->getPHID();
$results = parent::expandTransactions($object, $xactions);
$is_unassigned = ($object->getOwnerPHID() === null);
$any_assign = false;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() ==
ManiphestTaskOwnerTransaction::TRANSACTIONTYPE) {
$any_assign = true;
break;
}
}
$is_open = !$object->isClosed();
$new_status = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
$new_status = $xaction->getNewValue();
break;
}
}
if ($new_status === null) {
$is_closing = false;
} else {
$is_closing = ManiphestTaskStatus::isClosedStatus($new_status);
}
// If the task is not assigned, not being assigned, currently open, and
// being closed, try to assign the actor as the owner.
if ($is_unassigned && !$any_assign && $is_open && $is_closing) {
$is_claim = ManiphestTaskStatus::isClaimStatus($new_status);
// Don't assign the actor if they aren't a real user.
// Don't claim the task if the status is configured to not claim.
if ($actor_phid && $is_claim) {
$results[] = id(new ManiphestTransaction())
->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE)
->setNewValue($actor_phid);
}
}
// Automatically subscribe the author when they create a task.
if ($this->getIsNewObject()) {
if ($actor_phid) {
$results[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue(
array(
'+' => array($actor_phid => $actor_phid),
));
}
}
$send_notifications = PhabricatorNotificationClient::isEnabled();
if ($send_notifications) {
$this->oldProjectPHIDs = $this->loadProjectPHIDs($object);
}
return $results;
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$results = parent::expandTransaction($object, $xaction);
$type = $xaction->getTransactionType();
switch ($type) {
case PhabricatorTransactions::TYPE_COLUMNS:
try {
$more_xactions = $this->buildMoveTransaction($object, $xaction);
foreach ($more_xactions as $more_xaction) {
$results[] = $more_xaction;
}
} catch (Exception $ex) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
$this->moreValidationErrors[] = $error;
}
break;
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
// If this is a no-op update, don't expand it.
$old_value = $object->getOwnerPHID();
$new_value = $xaction->getNewValue();
if ($old_value === $new_value) {
break;
}
// When a task is reassigned, move the old owner to the subscriber
// list so they're still in the loop.
if ($old_value) {
$results[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setIgnoreOnNoEffect(true)
->setNewValue(
array(
'+' => array($old_value => $old_value),
));
}
break;
}
return $results;
}
private function buildMoveTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$actor = $this->getActor();
$new = $xaction->getNewValue();
if (!is_array($new)) {
$this->validateColumnPHID($new);
$new = array($new);
}
$relative_phids = array();
foreach ($new as $key => $value) {
if (!is_array($value)) {
$this->validateColumnPHID($value);
$value = array(
'columnPHID' => $value,
);
}
PhutilTypeSpec::checkMap(
$value,
array(
'columnPHID' => 'string',
'beforePHIDs' => 'optional list<string>',
'afterPHIDs' => 'optional list<string>',
// Deprecated older variations of "beforePHIDs" and "afterPHIDs".
'beforePHID' => 'optional string',
'afterPHID' => 'optional string',
));
$value = $value + array(
'beforePHIDs' => array(),
'afterPHIDs' => array(),
);
// Normalize the legacy keys "beforePHID" and "afterPHID" keys to the
// modern format.
if (!empty($value['afterPHID'])) {
if ($value['afterPHIDs']) {
throw new Exception(
pht(
'Transaction specifies both "afterPHID" and "afterPHIDs". '.
'Specify only "afterPHIDs".'));
}
$value['afterPHIDs'] = array($value['afterPHID']);
unset($value['afterPHID']);
}
if (isset($value['beforePHID'])) {
if ($value['beforePHIDs']) {
throw new Exception(
pht(
'Transaction specifies both "beforePHID" and "beforePHIDs". '.
'Specify only "beforePHIDs".'));
}
$value['beforePHIDs'] = array($value['beforePHID']);
unset($value['beforePHID']);
}
foreach ($value['beforePHIDs'] as $phid) {
$relative_phids[] = $phid;
}
foreach ($value['afterPHIDs'] as $phid) {
$relative_phids[] = $phid;
}
$new[$key] = $value;
}
// We require that objects you specify in "beforePHIDs" or "afterPHIDs"
// are real objects which exist and which you have permission to view.
// If you provide other objects, we remove them from the specification.
if ($relative_phids) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($actor)
->withPHIDs($relative_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
foreach ($new as $key => $value) {
$value['afterPHIDs'] = $this->filterValidPHIDs(
$value['afterPHIDs'],
$objects);
$value['beforePHIDs'] = $this->filterValidPHIDs(
$value['beforePHIDs'],
$objects);
$new[$key] = $value;
}
$column_phids = ipull($new, 'columnPHID');
if ($column_phids) {
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($actor)
->withPHIDs($column_phids)
->execute();
$columns = mpull($columns, null, 'getPHID');
} else {
$columns = array();
}
$board_phids = mpull($columns, 'getProjectPHID');
$object_phid = $object->getPHID();
// Note that we may not have an object PHID if we're creating a new
// object.
$object_phids = array();
if ($object_phid) {
$object_phids[] = $object_phid;
}
if ($object_phids) {
$layout_engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($this->getActor())
->setBoardPHIDs($board_phids)
->setObjectPHIDs($object_phids)
->setFetchAllBoards(true)
->executeLayout();
}
foreach ($new as $key => $spec) {
$column_phid = $spec['columnPHID'];
$column = idx($columns, $column_phid);
if (!$column) {
throw new Exception(
pht(
'Column move transaction specifies column PHID "%s", but there '.
'is no corresponding column with this PHID.',
$column_phid));
}
$board_phid = $column->getProjectPHID();
if ($object_phid) {
$old_columns = $layout_engine->getObjectColumns(
$board_phid,
$object_phid);
$old_column_phids = mpull($old_columns, 'getPHID');
} else {
$old_column_phids = array();
}
$spec += array(
'boardPHID' => $board_phid,
'fromColumnPHIDs' => $old_column_phids,
);
// Check if the object is already in this column, and isn't being moved.
// We can just drop this column change if it has no effect.
$from_map = array_fuse($spec['fromColumnPHIDs']);
$already_here = isset($from_map[$column_phid]);
$is_reordering = ($spec['afterPHIDs'] || $spec['beforePHIDs']);
if ($already_here && !$is_reordering) {
unset($new[$key]);
} else {
$new[$key] = $spec;
}
}
$new = array_values($new);
$xaction->setNewValue($new);
$more = array();
// If we're moving the object into a column and it does not already belong
// in the column, add the appropriate board. For normal columns, this
// is the board PHID. For proxy columns, it is the proxy PHID, unless the
// object is already a member of some descendant of the proxy PHID.
// The major case where this can happen is moves via the API, but it also
// happens when a user drags a task from the "Backlog" to a milestone
// column.
if ($object_phid) {
$current_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
$object_phid,
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
$current_phids = array_fuse($current_phids);
} else {
$current_phids = array();
}
$add_boards = array();
foreach ($new as $move) {
$column_phid = $move['columnPHID'];
$board_phid = $move['boardPHID'];
$column = $columns[$column_phid];
$proxy_phid = $column->getProxyPHID();
// If this is a normal column, add the board if the object isn't already
// associated.
if (!$proxy_phid) {
if (!isset($current_phids[$board_phid])) {
$add_boards[] = $board_phid;
}
continue;
}
// If this is a proxy column but the object is already associated with
// the proxy board, we don't need to do anything.
if (isset($current_phids[$proxy_phid])) {
continue;
}
// If this a proxy column and the object is already associated with some
// descendant of the proxy board, we also don't need to do anything.
$descendants = id(new PhabricatorProjectQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withAncestorProjectPHIDs(array($proxy_phid))
->execute();
$found_descendant = false;
foreach ($descendants as $descendant) {
if (isset($current_phids[$descendant->getPHID()])) {
$found_descendant = true;
break;
}
}
if ($found_descendant) {
continue;
}
// Otherwise, we're moving the object to a proxy column which it is not
// a member of yet, so add an association to the column's proxy board.
$add_boards[] = $proxy_phid;
}
if ($add_boards) {
$more[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
->setIgnoreOnNoEffect(true)
->setNewValue(
array(
'+' => array_fuse($add_boards),
));
}
return $more;
}
private function applyBoardMove($object, array $move) {
$board_phid = $move['boardPHID'];
$column_phid = $move['columnPHID'];
$before_phids = $move['beforePHIDs'];
$after_phids = $move['afterPHIDs'];
$object_phid = $object->getPHID();
// We're doing layout with the omnipotent viewer to make sure we don't
// remove positions in columns that exist, but which the actual actor
// can't see.
$omnipotent_viewer = PhabricatorUser::getOmnipotentUser();
$select_phids = array($board_phid);
$descendants = id(new PhabricatorProjectQuery())
->setViewer($omnipotent_viewer)
->withAncestorProjectPHIDs($select_phids)
->execute();
foreach ($descendants as $descendant) {
$select_phids[] = $descendant->getPHID();
}
$board_tasks = id(new ManiphestTaskQuery())
->setViewer($omnipotent_viewer)
->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
array($select_phids))
->execute();
$board_tasks = mpull($board_tasks, null, 'getPHID');
$board_tasks[$object_phid] = $object;
// Make sure tasks are sorted by ID, so we lay out new positions in
// a consistent way.
$board_tasks = msort($board_tasks, 'getID');
$object_phids = array_keys($board_tasks);
$engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($omnipotent_viewer)
->setBoardPHIDs(array($board_phid))
->setObjectPHIDs($object_phids)
->executeLayout();
// TODO: This logic needs to be revised when we legitimately support
// multiple column positions.
$columns = $engine->getObjectColumns($board_phid, $object_phid);
foreach ($columns as $column) {
$engine->queueRemovePosition(
$board_phid,
$column->getPHID(),
$object_phid);
}
$engine->queueAddPosition(
$board_phid,
$column_phid,
$object_phid,
$after_phids,
$before_phids);
$engine->applyPositionUpdates();
}
private function validateColumnPHID($value) {
if (phid_get_type($value) == PhabricatorProjectColumnPHIDType::TYPECONST) {
return;
}
throw new Exception(
pht(
'When moving objects between columns on a board, columns must '.
'be identified by PHIDs. This transaction uses "%s" to identify '.
'a column, but that is not a valid column PHID.',
$value));
}
private function getLockValidationErrors($object, array $xactions) {
$errors = array();
$old_owner = $object->getOwnerPHID();
$old_status = $object->getStatus();
$new_owner = $old_owner;
$new_status = $old_status;
$owner_xaction = null;
$status_xaction = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case ManiphestTaskOwnerTransaction::TRANSACTIONTYPE:
$new_owner = $xaction->getNewValue();
$owner_xaction = $xaction;
break;
case ManiphestTaskStatusTransaction::TRANSACTIONTYPE:
$new_status = $xaction->getNewValue();
$status_xaction = $xaction;
break;
}
}
$actor_phid = $this->getActingAsPHID();
$was_locked = ManiphestTaskStatus::areEditsLockedInStatus(
$old_status);
$now_locked = ManiphestTaskStatus::areEditsLockedInStatus(
$new_status);
if (!$now_locked) {
// If we're not ending in an edit-locked status, everything is good.
} else if ($new_owner !== null) {
// If we ending the edit with some valid owner, this is allowed for
// now. We might need to revisit this.
} else {
// The edits end with the task locked and unowned. No one will be able
// to edit it, so we forbid this. We try to be specific about what the
// user did wrong.
$owner_changed = ($old_owner && !$new_owner);
$status_changed = ($was_locked !== $now_locked);
$message = null;
if ($status_changed && $owner_changed) {
$message = pht(
'You can not lock this task and unassign it at the same time '.
'because no one will be able to edit it anymore. Lock the task '.
'or remove the owner, but not both.');
$problem_xaction = $status_xaction;
} else if ($status_changed) {
$message = pht(
'You can not lock this task because it does not have an owner. '.
'No one would be able to edit the task. Assign the task to an '.
'owner before locking it.');
$problem_xaction = $status_xaction;
} else if ($owner_changed) {
$message = pht(
'You can not remove the owner of this task because it is locked '.
'and no one would be able to edit the task. Reassign the task or '.
'unlock it before removing the owner.');
$problem_xaction = $owner_xaction;
} else {
// If the task was already broken, we don't have a transaction to
// complain about so just let it through. In theory, this is
// impossible since policy rules should kick in before we get here.
}
if ($message) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$problem_xaction->getTransactionType(),
pht('Lock Error'),
$message,
$problem_xaction);
}
}
return $errors;
}
private function filterValidPHIDs($phid_list, array $object_map) {
foreach ($phid_list as $key => $phid) {
if (isset($object_map[$phid])) {
continue;
}
unset($phid_list[$key]);
}
return array_values($phid_list);
}
protected function didApplyTransactions($object, array $xactions) {
$send_notifications = PhabricatorNotificationClient::isEnabled();
if ($send_notifications) {
$old_phids = $this->oldProjectPHIDs;
$new_phids = $this->loadProjectPHIDs($object);
// We want to emit update notifications for all old and new tagged
// projects, and all parents of those projects. For example, if an
// edit removes project "A > B" from a task, the "A" workboard should
// receive an update event.
$project_phids = array_fuse($old_phids) + array_fuse($new_phids);
$project_phids = array_keys($project_phids);
if ($project_phids) {
$projects = id(new PhabricatorProjectQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($project_phids)
->execute();
$notify_projects = array();
foreach ($projects as $project) {
$notify_projects[$project->getPHID()] = $project;
foreach ($project->getAncestorProjects() as $ancestor) {
$notify_projects[$ancestor->getPHID()] = $ancestor;
}
}
foreach ($notify_projects as $key => $project) {
if (!$project->getHasWorkboard()) {
unset($notify_projects[$key]);
}
}
$notify_phids = array_keys($notify_projects);
if ($notify_phids) {
$data = array(
'type' => 'workboards',
'subscribers' => $notify_phids,
);
PhabricatorNotificationClient::tryToPostMessage($data);
}
}
}
return $xactions;
}
private function loadProjectPHIDs(ManiphestTask $task) {
if (!$task->getPHID()) {
return array();
}
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($task->getPHID()))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
return $edge_query->getDestinationPHIDs();
}
}
diff --git a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
index 1aa544de57..b43b914d96 100644
--- a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
+++ b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
@@ -1,73 +1,73 @@
<?php
final class HeraldManiphestTaskAdapter extends HeraldAdapter {
private $task;
protected function newObject() {
return new ManiphestTask();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to tasks being created or updated.');
}
public function isTestAdapterForObject($object) {
return ($object instanceof ManiphestTask);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when a task is created or updated.');
}
protected function initializeNewAdapter() {
$this->task = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setTask(ManiphestTask $task) {
$this->task = $task;
return $this;
}
public function getTask() {
return $this->task;
}
public function setObject($object) {
$this->task = $object;
return $this;
}
public function getObject() {
return $this->task;
}
public function getAdapterContentName() {
return pht('Maniphest Tasks');
}
public function getHeraldName() {
return 'T'.$this->getTask()->getID();
}
}
diff --git a/src/applications/maniphest/phid/ManiphestTaskPHIDType.php b/src/applications/maniphest/phid/ManiphestTaskPHIDType.php
index 3b3c4a203f..1b0165fec7 100644
--- a/src/applications/maniphest/phid/ManiphestTaskPHIDType.php
+++ b/src/applications/maniphest/phid/ManiphestTaskPHIDType.php
@@ -1,76 +1,76 @@
<?php
final class ManiphestTaskPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'TASK';
public function getTypeName() {
return pht('Maniphest Task');
}
public function newObject() {
return new ManiphestTask();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ManiphestTaskQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$task = $objects[$phid];
$id = $task->getID();
$title = $task->getTitle();
$handle->setName("T{$id}");
$handle->setFullName("T{$id}: {$title}");
$handle->setURI("/T{$id}");
if ($task->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^T\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new ManiphestTaskQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php
index 8bbf976564..c206bd6599 100644
--- a/src/applications/maniphest/query/ManiphestTaskQuery.php
+++ b/src/applications/maniphest/query/ManiphestTaskQuery.php
@@ -1,1054 +1,1054 @@
<?php
/**
* Query tasks by specific criteria. This class uses the higher-performance
* but less-general Maniphest indexes to satisfy queries.
*/
final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $taskIDs;
private $taskPHIDs;
private $authorPHIDs;
private $ownerPHIDs;
private $noOwner;
private $anyOwner;
private $subscriberPHIDs;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $dateModifiedAfter;
private $dateModifiedBefore;
private $bridgedObjectPHIDs;
private $hasOpenParents;
private $hasOpenSubtasks;
private $parentTaskIDs;
private $subtaskIDs;
private $subtypes;
private $closedEpochMin;
private $closedEpochMax;
private $closerPHIDs;
private $columnPHIDs;
private $specificGroupByProjectPHID;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_RESOLVED = 'status-resolved';
const STATUS_WONTFIX = 'status-wontfix';
const STATUS_INVALID = 'status-invalid';
const STATUS_SPITE = 'status-spite';
const STATUS_DUPLICATE = 'status-duplicate';
private $statuses;
private $priorities;
private $subpriorities;
private $groupBy = 'group-none';
const GROUP_NONE = 'group-none';
const GROUP_PRIORITY = 'group-priority';
const GROUP_OWNER = 'group-owner';
const GROUP_STATUS = 'group-status';
const GROUP_PROJECT = 'group-project';
const ORDER_PRIORITY = 'order-priority';
const ORDER_CREATED = 'order-created';
const ORDER_MODIFIED = 'order-modified';
const ORDER_TITLE = 'order-title';
private $needSubscriberPHIDs;
private $needProjectPHIDs;
public function withAuthors(array $authors) {
$this->authorPHIDs = $authors;
return $this;
}
public function withIDs(array $ids) {
$this->taskIDs = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->taskPHIDs = $phids;
return $this;
}
public function withOwners(array $owners) {
if ($owners === array()) {
throw new Exception(pht('Empty withOwners() constraint is not valid.'));
}
$no_owner = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN;
$any_owner = PhabricatorPeopleAnyOwnerDatasource::FUNCTION_TOKEN;
foreach ($owners as $k => $phid) {
if ($phid === $no_owner || $phid === null) {
$this->noOwner = true;
unset($owners[$k]);
break;
}
if ($phid === $any_owner) {
$this->anyOwner = true;
unset($owners[$k]);
break;
}
}
if ($owners) {
$this->ownerPHIDs = $owners;
}
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withPriorities(array $priorities) {
$this->priorities = $priorities;
return $this;
}
public function withSubpriorities(array $subpriorities) {
$this->subpriorities = $subpriorities;
return $this;
}
public function withSubscribers(array $subscribers) {
$this->subscriberPHIDs = $subscribers;
return $this;
}
public function setGroupBy($group) {
$this->groupBy = $group;
switch ($this->groupBy) {
case self::GROUP_NONE:
$vector = array();
break;
case self::GROUP_PRIORITY:
$vector = array('priority');
break;
case self::GROUP_OWNER:
$vector = array('owner');
break;
case self::GROUP_STATUS:
$vector = array('status');
break;
case self::GROUP_PROJECT:
$vector = array('project');
break;
}
$this->setGroupVector($vector);
return $this;
}
public function withOpenSubtasks($value) {
$this->hasOpenSubtasks = $value;
return $this;
}
public function withOpenParents($value) {
$this->hasOpenParents = $value;
return $this;
}
public function withParentTaskIDs(array $ids) {
$this->parentTaskIDs = $ids;
return $this;
}
public function withSubtaskIDs(array $ids) {
$this->subtaskIDs = $ids;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withDateModifiedBefore($date_modified_before) {
$this->dateModifiedBefore = $date_modified_before;
return $this;
}
public function withDateModifiedAfter($date_modified_after) {
$this->dateModifiedAfter = $date_modified_after;
return $this;
}
public function withClosedEpochBetween($min, $max) {
$this->closedEpochMin = $min;
$this->closedEpochMax = $max;
return $this;
}
public function withCloserPHIDs(array $phids) {
$this->closerPHIDs = $phids;
return $this;
}
public function needSubscriberPHIDs($bool) {
$this->needSubscriberPHIDs = $bool;
return $this;
}
public function needProjectPHIDs($bool) {
$this->needProjectPHIDs = $bool;
return $this;
}
public function withBridgedObjectPHIDs(array $phids) {
$this->bridgedObjectPHIDs = $phids;
return $this;
}
public function withSubtypes(array $subtypes) {
$this->subtypes = $subtypes;
return $this;
}
public function withColumnPHIDs(array $column_phids) {
$this->columnPHIDs = $column_phids;
return $this;
}
public function withSpecificGroupByProjectPHID($project_phid) {
$this->specificGroupByProjectPHID = $project_phid;
return $this;
}
public function newResultObject() {
return new ManiphestTask();
}
protected function loadPage() {
$task_dao = new ManiphestTask();
$conn = $task_dao->establishConnection('r');
$where = $this->buildWhereClause($conn);
$group_column = qsprintf($conn, '');
switch ($this->groupBy) {
case self::GROUP_PROJECT:
$group_column = qsprintf(
$conn,
', projectGroupName.indexedObjectPHID projectGroupPHID');
break;
}
$rows = queryfx_all(
$conn,
'%Q %Q FROM %T task %Q %Q %Q %Q %Q %Q',
$this->buildSelectClause($conn),
$group_column,
$task_dao->getTableName(),
$this->buildJoinClause($conn),
$where,
$this->buildGroupClause($conn),
$this->buildHavingClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
switch ($this->groupBy) {
case self::GROUP_PROJECT:
$data = ipull($rows, null, 'id');
break;
default:
$data = $rows;
break;
}
$data = $this->didLoadRawRows($data);
$tasks = $task_dao->loadAllFromArray($data);
switch ($this->groupBy) {
case self::GROUP_PROJECT:
$results = array();
foreach ($rows as $row) {
$task = clone $tasks[$row['id']];
$task->attachGroupByProjectPHID($row['projectGroupPHID']);
$results[] = $task;
}
$tasks = $results;
break;
}
return $tasks;
}
protected function willFilterPage(array $tasks) {
if ($this->groupBy == self::GROUP_PROJECT) {
// We should only return project groups which the user can actually see.
$project_phids = mpull($tasks, 'getGroupByProjectPHID');
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->execute();
$projects = mpull($projects, null, 'getPHID');
foreach ($tasks as $key => $task) {
if (!$task->getGroupByProjectPHID()) {
// This task is either not tagged with any projects, or only tagged
// with projects which we're ignoring because they're being queried
// for explicitly.
continue;
}
if (empty($projects[$task->getGroupByProjectPHID()])) {
unset($tasks[$key]);
}
}
}
return $tasks;
}
protected function didFilterPage(array $tasks) {
$phids = mpull($tasks, 'getPHID');
if ($this->needProjectPHIDs) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($phids)
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($tasks as $task) {
$project_phids = $edge_query->getDestinationPHIDs(
array($task->getPHID()));
$task->attachProjectPHIDs($project_phids);
}
}
if ($this->needSubscriberPHIDs) {
$subscriber_sets = id(new PhabricatorSubscribersQuery())
->withObjectPHIDs($phids)
->execute();
foreach ($tasks as $task) {
$subscribers = idx($subscriber_sets, $task->getPHID(), array());
$task->attachSubscriberPHIDs($subscribers);
}
}
return $tasks;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
$where[] = $this->buildStatusWhereClause($conn);
$where[] = $this->buildOwnerWhereClause($conn);
if ($this->taskIDs !== null) {
$where[] = qsprintf(
$conn,
'task.id in (%Ld)',
$this->taskIDs);
}
if ($this->taskPHIDs !== null) {
$where[] = qsprintf(
$conn,
'task.phid in (%Ls)',
$this->taskPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'task.status IN (%Ls)',
$this->statuses);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'task.authorPHID in (%Ls)',
$this->authorPHIDs);
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn,
'task.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn,
'task.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->dateModifiedAfter) {
$where[] = qsprintf(
$conn,
'task.dateModified >= %d',
$this->dateModifiedAfter);
}
if ($this->dateModifiedBefore) {
$where[] = qsprintf(
$conn,
'task.dateModified <= %d',
$this->dateModifiedBefore);
}
if ($this->closedEpochMin !== null) {
$where[] = qsprintf(
$conn,
'task.closedEpoch >= %d',
$this->closedEpochMin);
}
if ($this->closedEpochMax !== null) {
$where[] = qsprintf(
$conn,
'task.closedEpoch <= %d',
$this->closedEpochMax);
}
if ($this->closerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'task.closerPHID IN (%Ls)',
$this->closerPHIDs);
}
if ($this->priorities !== null) {
$where[] = qsprintf(
$conn,
'task.priority IN (%Ld)',
$this->priorities);
}
if ($this->bridgedObjectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'task.bridgedObjectPHID IN (%Ls)',
$this->bridgedObjectPHIDs);
}
if ($this->subtypes !== null) {
$where[] = qsprintf(
$conn,
'task.subtype IN (%Ls)',
$this->subtypes);
}
if ($this->columnPHIDs !== null) {
$viewer = $this->getViewer();
$columns = id(new PhabricatorProjectColumnQuery())
->setParentQuery($this)
->setViewer($viewer)
->withPHIDs($this->columnPHIDs)
->execute();
if (!$columns) {
throw new PhabricatorEmptyQueryException();
}
// We must do board layout before we move forward because the column
// positions may not yet exist otherwise. An example is that newly
// created tasks may not yet be positioned in the backlog column.
$projects = mpull($columns, 'getProject');
$projects = mpull($projects, null, 'getPHID');
// The board layout engine needs to know about every object that it's
// going to be asked to do layout for. For now, we're just doing layout
// on every object on the boards. In the future, we could do layout on a
// smaller set of objects by using the constraints on this Query. For
// example, if the caller is only asking for open tasks, we only need
// to do layout on open tasks.
// This fetches too many objects (every type of object tagged with the
// project, not just tasks). We could narrow it by querying the edge
// table on the Maniphest side, but there's currently no way to build
// that query with EdgeQuery.
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($projects))
->withEdgeTypes(
array(
PhabricatorProjectProjectHasObjectEdgeType::EDGECONST,
));
$edge_query->execute();
$all_phids = $edge_query->getDestinationPHIDs();
// Since we overfetched PHIDs, filter out any non-tasks we got back.
foreach ($all_phids as $key => $phid) {
if (phid_get_type($phid) !== ManiphestTaskPHIDType::TYPECONST) {
unset($all_phids[$key]);
}
}
// If there are no tasks on the relevant boards, this query can't
// possibly hit anything so we're all done.
$task_phids = array_fuse($all_phids);
if (!$task_phids) {
throw new PhabricatorEmptyQueryException();
}
// We know everything we need to know, so perform board layout.
$engine = id(new PhabricatorBoardLayoutEngine())
->setViewer($viewer)
->setFetchAllBoards(true)
->setBoardPHIDs(array_keys($projects))
->setObjectPHIDs($task_phids)
->executeLayout();
// Find the tasks that are in the constraint columns after board layout
// completes.
$select_phids = array();
foreach ($columns as $column) {
$in_column = $engine->getColumnObjectPHIDs(
$column->getProjectPHID(),
$column->getPHID());
foreach ($in_column as $phid) {
$select_phids[$phid] = $phid;
}
}
if (!$select_phids) {
throw new PhabricatorEmptyQueryException();
}
$where[] = qsprintf(
$conn,
'task.phid IN (%Ls)',
$select_phids);
}
if ($this->specificGroupByProjectPHID !== null) {
$where[] = qsprintf(
$conn,
'projectGroupName.indexedObjectPHID = %s',
$this->specificGroupByProjectPHID);
}
return $where;
}
private function buildStatusWhereClause(AphrontDatabaseConnection $conn) {
static $map = array(
self::STATUS_RESOLVED => ManiphestTaskStatus::STATUS_CLOSED_RESOLVED,
self::STATUS_WONTFIX => ManiphestTaskStatus::STATUS_CLOSED_WONTFIX,
self::STATUS_INVALID => ManiphestTaskStatus::STATUS_CLOSED_INVALID,
self::STATUS_SPITE => ManiphestTaskStatus::STATUS_CLOSED_SPITE,
self::STATUS_DUPLICATE => ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE,
);
switch ($this->status) {
case self::STATUS_ANY:
return null;
case self::STATUS_OPEN:
return qsprintf(
$conn,
'task.status IN (%Ls)',
ManiphestTaskStatus::getOpenStatusConstants());
case self::STATUS_CLOSED:
return qsprintf(
$conn,
'task.status IN (%Ls)',
ManiphestTaskStatus::getClosedStatusConstants());
default:
$constant = idx($map, $this->status);
if (!$constant) {
throw new Exception(pht("Unknown status query '%s'!", $this->status));
}
return qsprintf(
$conn,
'task.status = %s',
$constant);
}
}
private function buildOwnerWhereClause(AphrontDatabaseConnection $conn) {
$subclause = array();
if ($this->noOwner) {
$subclause[] = qsprintf(
$conn,
'task.ownerPHID IS NULL');
}
if ($this->anyOwner) {
$subclause[] = qsprintf(
$conn,
'task.ownerPHID IS NOT NULL');
}
if ($this->ownerPHIDs !== null) {
$subclause[] = qsprintf(
$conn,
'task.ownerPHID IN (%Ls)',
$this->ownerPHIDs);
}
if (!$subclause) {
return qsprintf($conn, '');
}
return qsprintf($conn, '%LO', $subclause);
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$open_statuses = ManiphestTaskStatus::getOpenStatusConstants();
$edge_table = PhabricatorEdgeConfig::TABLE_NAME_EDGE;
$task_table = $this->newResultObject()->getTableName();
$parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
$subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
$joins = array();
if ($this->hasOpenParents !== null) {
if ($this->hasOpenParents) {
$join_type = qsprintf($conn, 'JOIN');
} else {
$join_type = qsprintf($conn, 'LEFT JOIN');
}
$joins[] = qsprintf(
$conn,
'%Q %T e_parent
ON e_parent.src = task.phid
AND e_parent.type = %d
%Q %T parent
ON e_parent.dst = parent.phid
AND parent.status IN (%Ls)',
$join_type,
$edge_table,
$parent_type,
$join_type,
$task_table,
$open_statuses);
}
if ($this->hasOpenSubtasks !== null) {
if ($this->hasOpenSubtasks) {
$join_type = qsprintf($conn, 'JOIN');
} else {
$join_type = qsprintf($conn, 'LEFT JOIN');
}
$joins[] = qsprintf(
$conn,
'%Q %T e_subtask
ON e_subtask.src = task.phid
AND e_subtask.type = %d
%Q %T subtask
ON e_subtask.dst = subtask.phid
AND subtask.status IN (%Ls)',
$join_type,
$edge_table,
$subtask_type,
$join_type,
$task_table,
$open_statuses);
}
if ($this->subscriberPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T e_ccs ON e_ccs.src = task.phid '.
'AND e_ccs.type = %s '.
'AND e_ccs.dst in (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasSubscriberEdgeType::EDGECONST,
$this->subscriberPHIDs);
}
switch ($this->groupBy) {
case self::GROUP_PROJECT:
$ignore_group_phids = $this->getIgnoreGroupedProjectPHIDs();
if ($ignore_group_phids) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T projectGroup ON task.phid = projectGroup.src
AND projectGroup.type = %d
AND projectGroup.dst NOT IN (%Ls)',
$edge_table,
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
$ignore_group_phids);
} else {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T projectGroup ON task.phid = projectGroup.src
AND projectGroup.type = %d',
$edge_table,
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
}
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T projectGroupName
ON projectGroup.dst = projectGroupName.indexedObjectPHID',
id(new ManiphestNameIndex())->getTableName());
break;
}
if ($this->parentTaskIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T e_has_parent
ON e_has_parent.src = task.phid
AND e_has_parent.type = %d
JOIN %T has_parent
ON e_has_parent.dst = has_parent.phid
AND has_parent.id IN (%Ld)',
$edge_table,
$parent_type,
$task_table,
$this->parentTaskIDs);
}
if ($this->subtaskIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T e_has_subtask
ON e_has_subtask.src = task.phid
AND e_has_subtask.type = %d
JOIN %T has_subtask
ON e_has_subtask.dst = has_subtask.phid
AND has_subtask.id IN (%Ld)',
$edge_table,
$subtask_type,
$task_table,
$this->subtaskIDs);
}
$joins[] = parent::buildJoinClauseParts($conn);
return $joins;
}
protected function buildGroupClause(AphrontDatabaseConnection $conn) {
$joined_multiple_rows =
($this->hasOpenParents !== null) ||
($this->hasOpenSubtasks !== null) ||
($this->parentTaskIDs !== null) ||
($this->subtaskIDs !== null) ||
$this->shouldGroupQueryResultRows();
$joined_project_name = ($this->groupBy == self::GROUP_PROJECT);
// If we're joining multiple rows, we need to group the results by the
// task IDs.
if ($joined_multiple_rows) {
if ($joined_project_name) {
return qsprintf($conn, 'GROUP BY task.phid, projectGroup.dst');
} else {
return qsprintf($conn, 'GROUP BY task.phid');
}
}
return qsprintf($conn, '');
}
protected function buildHavingClauseParts(AphrontDatabaseConnection $conn) {
$having = parent::buildHavingClauseParts($conn);
if ($this->hasOpenParents !== null) {
if (!$this->hasOpenParents) {
$having[] = qsprintf(
$conn,
'COUNT(parent.phid) = 0');
}
}
if ($this->hasOpenSubtasks !== null) {
if (!$this->hasOpenSubtasks) {
$having[] = qsprintf(
$conn,
'COUNT(subtask.phid) = 0');
}
}
return $having;
}
/**
* Return project PHIDs which we should ignore when grouping tasks by
* project. For example, if a user issues a query like:
*
* Tasks tagged with all projects: Frontend, Bugs
*
* ...then we don't show "Frontend" or "Bugs" groups in the result set, since
* they're meaningless as all results are in both groups.
*
* Similarly, for queries like:
*
* Tasks tagged with any projects: Public Relations
*
* ...we ignore the single project, as every result is in that project. (In
* the case that there are several "any" projects, we do not ignore them.)
*
* @return list<phid> Project PHIDs which should be ignored in query
* construction.
*/
private function getIgnoreGroupedProjectPHIDs() {
// Maybe we should also exclude the "OPERATOR_NOT" PHIDs? It won't
// impact the results, but we might end up with a better query plan.
// Investigate this on real data? This is likely very rare.
$edge_types = array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
);
$phids = array();
$phids[] = $this->getEdgeLogicValues(
$edge_types,
array(
PhabricatorQueryConstraint::OPERATOR_AND,
));
$any = $this->getEdgeLogicValues(
$edge_types,
array(
PhabricatorQueryConstraint::OPERATOR_OR,
));
if (count($any) == 1) {
$phids[] = $any;
}
return array_mergev($phids);
}
public function getBuiltinOrders() {
$orders = array(
'priority' => array(
'vector' => array('priority', 'id'),
'name' => pht('Priority'),
'aliases' => array(self::ORDER_PRIORITY),
),
'updated' => array(
'vector' => array('updated', 'id'),
'name' => pht('Date Updated (Latest First)'),
'aliases' => array(self::ORDER_MODIFIED),
),
'outdated' => array(
'vector' => array('-updated', '-id'),
'name' => pht('Date Updated (Oldest First)'),
),
'closed' => array(
'vector' => array('closed', 'id'),
'name' => pht('Date Closed (Latest First)'),
),
'title' => array(
'vector' => array('title', 'id'),
'name' => pht('Title'),
'aliases' => array(self::ORDER_TITLE),
),
) + parent::getBuiltinOrders();
// Alias the "newest" builtin to the historical key for it.
$orders['newest']['aliases'][] = self::ORDER_CREATED;
$orders = array_select_keys(
$orders,
array(
'priority',
'updated',
'outdated',
'newest',
'oldest',
'closed',
'title',
)) + $orders;
return $orders;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'priority' => array(
'table' => 'task',
'column' => 'priority',
'type' => 'int',
),
'owner' => array(
'table' => 'task',
'column' => 'ownerOrdering',
'null' => 'head',
'reverse' => true,
'type' => 'string',
),
'status' => array(
'table' => 'task',
'column' => 'status',
'type' => 'string',
'reverse' => true,
),
'project' => array(
'table' => 'projectGroupName',
'column' => 'indexedObjectName',
'type' => 'string',
'null' => 'head',
'reverse' => true,
),
'title' => array(
'table' => 'task',
'column' => 'title',
'type' => 'string',
'reverse' => true,
),
'updated' => array(
'table' => 'task',
'column' => 'dateModified',
'type' => 'int',
),
'closed' => array(
'table' => 'task',
'column' => 'closedEpoch',
'type' => 'int',
'null' => 'tail',
),
);
}
protected function newPagingMapFromCursorObject(
PhabricatorQueryCursor $cursor,
array $keys) {
$task = $cursor->getObject();
$map = array(
'id' => (int)$task->getID(),
'priority' => (int)$task->getPriority(),
'owner' => $task->getOwnerOrdering(),
'status' => $task->getStatus(),
'title' => $task->getTitle(),
'updated' => (int)$task->getDateModified(),
'closed' => $task->getClosedEpoch(),
);
if (isset($keys['project'])) {
$value = null;
$group_phid = $task->getGroupByProjectPHID();
if ($group_phid) {
$paging_projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withPHIDs(array($group_phid))
->execute();
if ($paging_projects) {
$value = head($paging_projects)->getName();
}
}
$map['project'] = $value;
}
foreach ($keys as $key) {
if ($this->isCustomFieldOrderKey($key)) {
$map += $this->getPagingValueMapForCustomFields($task);
break;
}
}
return $map;
}
protected function newExternalCursorStringForResult($object) {
$id = $object->getID();
if ($this->groupBy == self::GROUP_PROJECT) {
return rtrim($id.'.'.$object->getGroupByProjectPHID(), '.');
}
return $id;
}
protected function newInternalCursorFromExternalCursor($cursor) {
list($task_id, $group_phid) = $this->parseCursor($cursor);
$cursor_object = parent::newInternalCursorFromExternalCursor($cursor);
if ($group_phid !== null) {
$project = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withPHIDs(array($group_phid))
->execute();
if (!$project) {
$this->throwCursorException(
pht(
'Group PHID ("%s") component of cursor ("%s") is not valid.',
$group_phid,
$cursor));
}
$cursor_object->getObject()->attachGroupByProjectPHID($group_phid);
}
return $cursor_object;
}
protected function applyExternalCursorConstraintsToQuery(
PhabricatorCursorPagedPolicyAwareQuery $subquery,
$cursor) {
list($task_id, $group_phid) = $this->parseCursor($cursor);
$subquery->withIDs(array($task_id));
if ($group_phid) {
$subquery->setGroupBy(self::GROUP_PROJECT);
// The subquery needs to return exactly one result. If a task is in
// several projects, the query may naturally return several results.
// Specify that we want only the particular instance of the task in
// the specified project.
$subquery->withSpecificGroupByProjectPHID($group_phid);
}
}
private function parseCursor($cursor) {
// Split a "123.PHID-PROJ-abcd" cursor into a "Task ID" part and a
// "Project PHID" part.
$parts = explode('.', $cursor, 2);
if (count($parts) < 2) {
$parts[] = null;
}
if (!phutil_nonempty_string($parts[1])) {
$parts[1] = null;
}
return $parts;
}
protected function getPrimaryTableAlias() {
return 'task';
}
public function getQueryApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
}
diff --git a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
index 4c69c604e4..361cdca7e4 100644
--- a/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
+++ b/src/applications/maniphest/query/ManiphestTaskSearchEngine.php
@@ -1,585 +1,585 @@
<?php
final class ManiphestTaskSearchEngine
extends PhabricatorApplicationSearchEngine {
private $showBatchControls;
private $baseURI;
private $isBoardView;
public function setIsBoardView($is_board_view) {
$this->isBoardView = $is_board_view;
return $this;
}
public function getIsBoardView() {
return $this->isBoardView;
}
public function setBaseURI($base_uri) {
$this->baseURI = $base_uri;
return $this;
}
public function getBaseURI() {
return $this->baseURI;
}
public function setShowBatchControls($show_batch_controls) {
$this->showBatchControls = $show_batch_controls;
return $this;
}
public function getResultTypeDescription() {
return pht('Maniphest Tasks');
}
public function getApplicationClassName() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function newQuery() {
return id(new ManiphestTaskQuery())
->needProjectPHIDs(true);
}
protected function buildCustomSearchFields() {
// Hide the "Subtypes" constraint from the web UI if the install only
// defines one task subtype, since it isn't of any use in this case.
$subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap();
$hide_subtypes = ($subtype_map->getCount() == 1);
return array(
id(new PhabricatorOwnersSearchField())
->setLabel(pht('Assigned To'))
->setKey('assignedPHIDs')
->setConduitKey('assigned')
->setAliases(array('assigned'))
->setDescription(
pht('Search for tasks owned by a user from a list.')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors'))
->setDescription(
pht('Search for tasks with given authors.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Statuses'))
->setKey('statuses')
->setAliases(array('status'))
->setDescription(
pht('Search for tasks with given statuses.'))
->setDatasource(new ManiphestTaskStatusFunctionDatasource()),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Priorities'))
->setKey('priorities')
->setAliases(array('priority'))
->setDescription(
pht('Search for tasks with given priorities.'))
->setConduitParameterType(new ConduitIntListParameterType())
->setDatasource(new ManiphestTaskPriorityDatasource()),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Subtypes'))
->setKey('subtypes')
->setAliases(array('subtype'))
->setDescription(
pht('Search for tasks with given subtypes.'))
->setDatasource(new ManiphestTaskSubtypeDatasource())
->setIsHidden($hide_subtypes),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Columns'))
->setKey('columnPHIDs')
->setAliases(array('column', 'columnPHID', 'columns')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Open Parents'))
->setKey('hasParents')
->setAliases(array('blocking'))
->setOptions(
pht('(Show All)'),
pht('Show Only Tasks With Open Parents'),
pht('Show Only Tasks Without Open Parents')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Open Subtasks'))
->setKey('hasSubtasks')
->setAliases(array('blocked'))
->setOptions(
pht('(Show All)'),
pht('Show Only Tasks With Open Subtasks'),
pht('Show Only Tasks Without Open Subtasks')),
id(new PhabricatorIDsSearchField())
->setLabel(pht('Parent IDs'))
->setKey('parentIDs')
->setAliases(array('parentID')),
id(new PhabricatorIDsSearchField())
->setLabel(pht('Subtask IDs'))
->setKey('subtaskIDs')
->setAliases(array('subtaskID')),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Group By'))
->setKey('group')
->setOptions($this->getGroupOptions()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Updated After'))
->setKey('modifiedStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Updated Before'))
->setKey('modifiedEnd'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Closed After'))
->setKey('closedStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Closed Before'))
->setKey('closedEnd'),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Closed By'))
->setKey('closerPHIDs')
->setAliases(array('closer', 'closerPHID', 'closers'))
->setDescription(pht('Search for tasks closed by certain users.')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Page Size'))
->setKey('limit'),
);
}
protected function getDefaultFieldOrder() {
return array(
'assignedPHIDs',
'projectPHIDs',
'authorPHIDs',
'subscriberPHIDs',
'statuses',
'priorities',
'subtypes',
'hasParents',
'hasSubtasks',
'parentIDs',
'subtaskIDs',
'group',
'order',
'ids',
'...',
'createdStart',
'createdEnd',
'modifiedStart',
'modifiedEnd',
'closedStart',
'closedEnd',
'closerPHIDs',
'limit',
);
}
protected function getHiddenFields() {
$keys = array();
if ($this->getIsBoardView()) {
$keys[] = 'group';
$keys[] = 'order';
$keys[] = 'limit';
}
return $keys;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['assignedPHIDs']) {
$query->withOwners($map['assignedPHIDs']);
}
if ($map['authorPHIDs']) {
$query->withAuthors($map['authorPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['priorities']) {
$query->withPriorities($map['priorities']);
}
if ($map['subtypes']) {
$query->withSubtypes($map['subtypes']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedBefore($map['createdEnd']);
}
if ($map['modifiedStart']) {
$query->withDateModifiedAfter($map['modifiedStart']);
}
if ($map['modifiedEnd']) {
$query->withDateModifiedBefore($map['modifiedEnd']);
}
if ($map['closedStart'] || $map['closedEnd']) {
$query->withClosedEpochBetween($map['closedStart'], $map['closedEnd']);
}
if ($map['closerPHIDs']) {
$query->withCloserPHIDs($map['closerPHIDs']);
}
if ($map['hasParents'] !== null) {
$query->withOpenParents($map['hasParents']);
}
if ($map['hasSubtasks'] !== null) {
$query->withOpenSubtasks($map['hasSubtasks']);
}
if ($map['parentIDs']) {
$query->withParentTaskIDs($map['parentIDs']);
}
if ($map['subtaskIDs']) {
$query->withSubtaskIDs($map['subtaskIDs']);
}
if ($map['columnPHIDs']) {
$query->withColumnPHIDs($map['columnPHIDs']);
}
$group = idx($map, 'group');
$group = idx($this->getGroupValues(), $group);
if ($group) {
$query->setGroupBy($group);
}
if ($map['ids']) {
$ids = $map['ids'];
foreach ($ids as $key => $id) {
$id = trim($id, ' Tt');
if (!$id || !is_numeric($id)) {
unset($ids[$key]);
} else {
$ids[$key] = $id;
}
}
if ($ids) {
$query->withIDs($ids);
}
}
return $query;
}
protected function getURI($path) {
if ($this->baseURI) {
return $this->baseURI.$path;
}
return '/maniphest/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['assigned'] = pht('Assigned');
$names['authored'] = pht('Authored');
$names['subscribed'] = pht('Subscribed');
}
$names['open'] = pht('Open Tasks');
$names['all'] = pht('All Tasks');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
switch ($query_key) {
case 'all':
return $query;
case 'assigned':
return $query
->setParameter('assignedPHIDs', array($viewer_phid))
->setParameter(
'statuses',
ManiphestTaskStatus::getOpenStatusConstants());
case 'subscribed':
return $query
->setParameter('subscriberPHIDs', array($viewer_phid))
->setParameter(
'statuses',
ManiphestTaskStatus::getOpenStatusConstants());
case 'open':
return $query
->setParameter(
'statuses',
ManiphestTaskStatus::getOpenStatusConstants());
case 'authored':
return $query
->setParameter('authorPHIDs', array($viewer_phid))
->setParameter('order', 'created')
->setParameter('group', 'none');
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getGroupOptions() {
return array(
'priority' => pht('Priority'),
'assigned' => pht('Assigned'),
'status' => pht('Status'),
'project' => pht('Project'),
'none' => pht('None'),
);
}
private function getGroupValues() {
return array(
'priority' => ManiphestTaskQuery::GROUP_PRIORITY,
'assigned' => ManiphestTaskQuery::GROUP_OWNER,
'status' => ManiphestTaskQuery::GROUP_STATUS,
'project' => ManiphestTaskQuery::GROUP_PROJECT,
'none' => ManiphestTaskQuery::GROUP_NONE,
);
}
protected function renderResultList(
array $tasks,
PhabricatorSavedQuery $saved,
array $handles) {
$viewer = $this->requireViewer();
if ($this->isPanelContext()) {
$can_bulk_edit = false;
} else {
$can_bulk_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$this->getApplication(),
ManiphestBulkEditCapability::CAPABILITY);
}
$list = id(new ManiphestTaskResultListView())
->setUser($viewer)
->setTasks($tasks)
->setSavedQuery($saved)
->setCanBatchEdit($can_bulk_edit)
->setShowBatchControls($this->showBatchControls);
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($list);
return $result;
}
protected function willUseSavedQuery(PhabricatorSavedQuery $saved) {
// The 'withUnassigned' parameter may be present in old saved queries from
// before parameterized typeaheads, and is retained for compatibility. We
// could remove it by migrating old saved queries.
$assigned_phids = $saved->getParameter('assignedPHIDs', array());
if ($saved->getParameter('withUnassigned')) {
$assigned_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN;
}
$saved->setParameter('assignedPHIDs', $assigned_phids);
// The 'projects' and other parameters may be present in old saved queries
// from before parameterized typeaheads.
$project_phids = $saved->getParameter('projectPHIDs', array());
$old = $saved->getParameter('projects', array());
foreach ($old as $phid) {
$project_phids[] = $phid;
}
$all = $saved->getParameter('allProjectPHIDs', array());
foreach ($all as $phid) {
$project_phids[] = $phid;
}
$any = $saved->getParameter('anyProjectPHIDs', array());
foreach ($any as $phid) {
$project_phids[] = 'any('.$phid.')';
}
$not = $saved->getParameter('excludeProjectPHIDs', array());
foreach ($not as $phid) {
$project_phids[] = 'not('.$phid.')';
}
$users = $saved->getParameter('userProjectPHIDs', array());
foreach ($users as $phid) {
$project_phids[] = 'projects('.$phid.')';
}
$no = $saved->getParameter('withNoProject');
if ($no) {
$project_phids[] = 'null()';
}
$saved->setParameter('projectPHIDs', $project_phids);
}
protected function getNewUserBody() {
$viewer = $this->requireViewer();
$create_button = id(new ManiphestEditEngine())
->setViewer($viewer)
->newNUXBUtton(pht('Create a Task'));
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Use Maniphest to track bugs, features, todos, or anything else '.
'you need to get done. Tasks assigned to you will appear here.'))
->addAction($create_button);
return $view;
}
protected function newExportFields() {
$fields = array(
id(new PhabricatorStringExportField())
->setKey('monogram')
->setLabel(pht('Monogram')),
id(new PhabricatorPHIDExportField())
->setKey('authorPHID')
->setLabel(pht('Author PHID')),
id(new PhabricatorStringExportField())
->setKey('author')
->setLabel(pht('Author')),
id(new PhabricatorPHIDExportField())
->setKey('ownerPHID')
->setLabel(pht('Owner PHID')),
id(new PhabricatorStringExportField())
->setKey('owner')
->setLabel(pht('Owner')),
id(new PhabricatorStringExportField())
->setKey('status')
->setLabel(pht('Status')),
id(new PhabricatorStringExportField())
->setKey('statusName')
->setLabel(pht('Status Name')),
id(new PhabricatorEpochExportField())
->setKey('dateClosed')
->setLabel(pht('Date Closed')),
id(new PhabricatorPHIDExportField())
->setKey('closerPHID')
->setLabel(pht('Closer PHID')),
id(new PhabricatorStringExportField())
->setKey('closer')
->setLabel(pht('Closer')),
id(new PhabricatorStringExportField())
->setKey('priority')
->setLabel(pht('Priority')),
id(new PhabricatorStringExportField())
->setKey('priorityName')
->setLabel(pht('Priority Name')),
id(new PhabricatorStringExportField())
->setKey('subtype')
->setLabel('Subtype'),
id(new PhabricatorURIExportField())
->setKey('uri')
->setLabel(pht('URI')),
id(new PhabricatorStringExportField())
->setKey('title')
->setLabel(pht('Title')),
id(new PhabricatorStringExportField())
->setKey('description')
->setLabel(pht('Description')),
);
if (ManiphestTaskPoints::getIsEnabled()) {
$fields[] = id(new PhabricatorDoubleExportField())
->setKey('points')
->setLabel('Points');
}
return $fields;
}
protected function newExportData(array $tasks) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($tasks as $task) {
$phids[] = $task->getAuthorPHID();
$phids[] = $task->getOwnerPHID();
$phids[] = $task->getCloserPHID();
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($tasks as $task) {
$author_phid = $task->getAuthorPHID();
if ($author_phid) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = null;
}
$owner_phid = $task->getOwnerPHID();
if ($owner_phid) {
$owner_name = $handles[$owner_phid]->getName();
} else {
$owner_name = null;
}
$closer_phid = $task->getCloserPHID();
if ($closer_phid) {
$closer_name = $handles[$closer_phid]->getName();
} else {
$closer_name = null;
}
$status_value = $task->getStatus();
$status_name = ManiphestTaskStatus::getTaskStatusName($status_value);
$priority_value = $task->getPriority();
$priority_name = ManiphestTaskPriority::getTaskPriorityName(
$priority_value);
$export[] = array(
'monogram' => $task->getMonogram(),
'authorPHID' => $author_phid,
'author' => $author_name,
'ownerPHID' => $owner_phid,
'owner' => $owner_name,
'status' => $status_value,
'statusName' => $status_name,
'priority' => $priority_value,
'priorityName' => $priority_name,
'points' => $task->getPoints(),
'subtype' => $task->getSubtype(),
'title' => $task->getTitle(),
'uri' => PhabricatorEnv::getProductionURI($task->getURI()),
'description' => $task->getDescription(),
'dateClosed' => $task->getClosedEpoch(),
'closerPHID' => $closer_phid,
'closer' => $closer_name,
);
}
return $export;
}
}
diff --git a/src/applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php
index 68fb521980..7b9e6f91ed 100644
--- a/src/applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php
+++ b/src/applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php
@@ -1,74 +1,74 @@
<?php
final class ManiphestTaskClosedStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'closed()';
public function getBrowseTitle() {
return pht('Browse Any Closed Status');
}
public function getPlaceholderText() {
return pht('Type closed()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function getDatasourceFunctions() {
return array(
'closed' => array(
'name' => pht('Any Closed Status'),
'summary' => pht('Find results with any closed status.'),
'description' => pht(
'This function includes results which have any closed status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildClosedResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = ManiphestTaskStatus::getTaskStatusMap();
foreach ($argv_list as $argv) {
foreach ($map as $status => $name) {
if (!ManiphestTaskStatus::isOpenStatus($status)) {
$results[] = $status;
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildClosedResult());
}
return $results;
}
private function buildClosedResult() {
$name = pht('Any Closed Status');
return $this->newFunctionResult()
->setName($name.' closed')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any closed status.'));
}
}
diff --git a/src/applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php
index 85a201fdba..b08cae0a9d 100644
--- a/src/applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php
+++ b/src/applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php
@@ -1,74 +1,74 @@
<?php
final class ManiphestTaskOpenStatusDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'open()';
public function getBrowseTitle() {
return pht('Browse Any Open Status');
}
public function getPlaceholderText() {
return pht('Type open()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function getDatasourceFunctions() {
return array(
'open' => array(
'name' => pht('Any Open Status'),
'summary' => pht('Find results with any open status.'),
'description' => pht(
'This function includes results which have any open status.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildOpenResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$map = ManiphestTaskStatus::getTaskStatusMap();
foreach ($argv_list as $argv) {
foreach ($map as $status => $name) {
if (ManiphestTaskStatus::isOpenStatus($status)) {
$results[] = $status;
}
}
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildOpenResult());
}
return $results;
}
private function buildOpenResult() {
$name = pht('Any Open Status');
return $this->newFunctionResult()
->setName($name.' open')
->setDisplayName($name)
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select any open status.'));
}
}
diff --git a/src/applications/maniphest/typeahead/ManiphestTaskPriorityDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskPriorityDatasource.php
index c4530f9bb3..db73f8d898 100644
--- a/src/applications/maniphest/typeahead/ManiphestTaskPriorityDatasource.php
+++ b/src/applications/maniphest/typeahead/ManiphestTaskPriorityDatasource.php
@@ -1,48 +1,48 @@
<?php
final class ManiphestTaskPriorityDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Priorities');
}
public function getPlaceholderText() {
return pht('Type a task priority name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
public function renderTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$priority_map = ManiphestTaskPriority::getTaskPriorityMap();
foreach ($priority_map as $value => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setIcon(ManiphestTaskPriority::getTaskPriorityIcon($value))
->setPHID($value)
->setName($name)
->addAttribute(pht('Priority'));
if (ManiphestTaskPriority::isDisabledPriority($value)) {
$result->setClosed(pht('Disabled'));
}
$results[$value] = $result;
}
return $results;
}
}
diff --git a/src/applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php
index 9d73ca994f..26bfacc520 100644
--- a/src/applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php
+++ b/src/applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php
@@ -1,54 +1,54 @@
<?php
final class ManiphestTaskStatusDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Statuses');
}
public function getPlaceholderText() {
return pht('Type a task status name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$status_map = ManiphestTaskStatus::getTaskStatusMap();
foreach ($status_map as $value => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setIcon(ManiphestTaskStatus::getStatusIcon($value))
->setPHID($value)
->setName($name);
if (ManiphestTaskStatus::isOpenStatus($value)) {
$result->addAttribute(pht('Open Status'));
} else {
$result->addAttribute(pht('Closed Status'));
}
if (ManiphestTaskStatus::isDisabledStatus($value)) {
$result->setClosed(pht('Disabled'));
}
$results[$value] = $result;
}
return $results;
}
}
diff --git a/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php b/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php
index cfa5592ccc..b24a0cfaad 100644
--- a/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php
+++ b/src/applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php
@@ -1,45 +1,45 @@
<?php
final class ManiphestTaskSubtypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Subtypes');
}
public function getPlaceholderText() {
return pht('Type a task subtype name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorManiphestApplication';
+ return PhabricatorManiphestApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap();
foreach ($subtype_map->getSubtypes() as $key => $subtype) {
$result = id(new PhabricatorTypeaheadResult())
->setIcon($subtype->getIcon())
->setColor($subtype->getColor())
->setPHID($key)
->setName($subtype->getName());
$results[$key] = $result;
}
return $results;
}
}
diff --git a/src/applications/meta/editor/PhabricatorApplicationEditEngine.php b/src/applications/meta/editor/PhabricatorApplicationEditEngine.php
index 7cad5d9242..b6442ba3a8 100644
--- a/src/applications/meta/editor/PhabricatorApplicationEditEngine.php
+++ b/src/applications/meta/editor/PhabricatorApplicationEditEngine.php
@@ -1,64 +1,64 @@
<?php
final class PhabricatorApplicationEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'application.application';
public function getEngineApplicationClass() {
- return 'PhabricatorApplicationsApplication';
+ return PhabricatorApplicationsApplication::class;
}
public function getEngineName() {
return pht('Applications');
}
public function getSummaryHeader() {
return pht('Configure Application Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Applications.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
throw new PhutilMethodNotImplementedException();
}
protected function newObjectQuery() {
return new PhabricatorApplicationQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Application');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Application: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Application');
}
protected function getObjectName() {
return pht('Application');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function buildCustomEditFields($object) {
return array();
}
}
diff --git a/src/applications/meta/editor/PhabricatorApplicationEditor.php b/src/applications/meta/editor/PhabricatorApplicationEditor.php
index 83003b4c27..99f291e6d8 100644
--- a/src/applications/meta/editor/PhabricatorApplicationEditor.php
+++ b/src/applications/meta/editor/PhabricatorApplicationEditor.php
@@ -1,46 +1,46 @@
<?php
final class PhabricatorApplicationEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorApplicationsApplication';
+ return PhabricatorApplicationsApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Application');
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return false;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array();
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
}
diff --git a/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php b/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php
index 946f56616d..b67ba1a023 100644
--- a/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php
+++ b/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorApplicationApplicationPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'APPS';
public function getTypeName() {
return pht('Application');
}
public function getTypeIcon() {
return 'fa-globe';
}
public function newObject() {
return null;
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorApplicationsApplication';
+ return PhabricatorApplicationsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorApplicationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$application = $objects[$phid];
$handle
->setName($application->getName())
->setURI($application->getApplicationURI())
->setIcon($application->getIcon());
}
}
}
diff --git a/src/applications/meta/query/PhabricatorAppSearchEngine.php b/src/applications/meta/query/PhabricatorAppSearchEngine.php
index 08283afc2e..b4d5d9b9c2 100644
--- a/src/applications/meta/query/PhabricatorAppSearchEngine.php
+++ b/src/applications/meta/query/PhabricatorAppSearchEngine.php
@@ -1,286 +1,286 @@
<?php
final class PhabricatorAppSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Applications');
}
public function getApplicationClassName() {
- return 'PhabricatorApplicationsApplication';
+ return PhabricatorApplicationsApplication::class;
}
public function getPageSize(PhabricatorSavedQuery $saved) {
return INF;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('name', $request->getStr('name'));
$saved->setParameter(
'installed',
$this->readBoolFromRequest($request, 'installed'));
$saved->setParameter(
'prototypes',
$this->readBoolFromRequest($request, 'prototypes'));
$saved->setParameter(
'firstParty',
$this->readBoolFromRequest($request, 'firstParty'));
$saved->setParameter(
'launchable',
$this->readBoolFromRequest($request, 'launchable'));
$saved->setParameter(
'appemails',
$this->readBoolFromRequest($request, 'appemails'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorApplicationQuery())
->setOrder(PhabricatorApplicationQuery::ORDER_NAME)
->withUnlisted(false);
$name = $saved->getParameter('name');
if (phutil_nonempty_string($name)) {
$query->withNameContains($name);
}
$installed = $saved->getParameter('installed');
if ($installed !== null) {
$query->withInstalled($installed);
}
$prototypes = $saved->getParameter('prototypes');
if ($prototypes === null) {
// NOTE: This is the old name of the 'prototypes' option, see T6084.
$prototypes = $saved->getParameter('beta');
$saved->setParameter('prototypes', $prototypes);
}
if ($prototypes !== null) {
$query->withPrototypes($prototypes);
}
$first_party = $saved->getParameter('firstParty');
if ($first_party !== null) {
$query->withFirstParty($first_party);
}
$launchable = $saved->getParameter('launchable');
if ($launchable !== null) {
$query->withLaunchable($launchable);
}
$appemails = $saved->getParameter('appemails');
if ($appemails !== null) {
$query->withApplicationEmailSupport($appemails);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$form
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name Contains'))
->setName('name')
->setValue($saved->getParameter('name')))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Installed'))
->setName('installed')
->setValue($this->getBoolFromQuery($saved, 'installed'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show Installed Applications'),
'false' => pht('Show Uninstalled Applications'),
)))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Prototypes'))
->setName('prototypes')
->setValue($this->getBoolFromQuery($saved, 'prototypes'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show Prototype Applications'),
'false' => pht('Show Released Applications'),
)))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Provenance'))
->setName('firstParty')
->setValue($this->getBoolFromQuery($saved, 'firstParty'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show First-Party Applications'),
'false' => pht('Show Third-Party Applications'),
)))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Launchable'))
->setName('launchable')
->setValue($this->getBoolFromQuery($saved, 'launchable'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show Launchable Applications'),
'false' => pht('Show Non-Launchable Applications'),
)))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Application Emails'))
->setName('appemails')
->setValue($this->getBoolFromQuery($saved, 'appemails'))
->setOptions(
array(
'' => pht('Show All Applications'),
'true' => pht('Show Applications w/ App Email Support'),
'false' => pht('Show Applications w/o App Email Support'),
)));
}
protected function getURI($path) {
return '/applications/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'launcher' => pht('Launcher'),
'all' => pht('All Applications'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'launcher':
return $query
->setParameter('installed', true)
->setParameter('launchable', true);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $all_applications,
PhabricatorSavedQuery $query,
array $handle) {
assert_instances_of($all_applications, 'PhabricatorApplication');
$all_applications = msort($all_applications, 'getName');
if ($query->getQueryKey() == 'launcher') {
$groups = mgroup($all_applications, 'getApplicationGroup');
} else {
$groups = array($all_applications);
}
$group_names = PhabricatorApplication::getApplicationGroups();
$groups = array_select_keys($groups, array_keys($group_names)) + $groups;
$results = array();
foreach ($groups as $group => $applications) {
if (count($groups) > 1) {
$results[] = phutil_tag(
'h1',
array(
'class' => 'phui-oi-list-header',
),
idx($group_names, $group, $group));
}
$list = new PHUIObjectItemListView();
foreach ($applications as $application) {
$icon = $application->getIcon();
if (!$icon) {
$icon = 'application';
}
$description = $application->getShortDescription();
$configure = id(new PHUIButtonView())
->setTag('a')
->setIcon('fa-gears')
->setHref('/applications/view/'.get_class($application).'/')
->setText(pht('Configure'))
->setColor(PHUIButtonView::GREY);
$name = $application->getName();
$item = id(new PHUIObjectItemView())
->setHeader($name)
->setImageIcon($icon)
->setSideColumn($configure);
if (!$application->isFirstParty()) {
$extension_tag = id(new PHUITagView())
->setName(pht('Extension'))
->setIcon('fa-plug')
->setColor(PHUITagView::COLOR_INDIGO)
->setType(PHUITagView::TYPE_SHADE)
->setSlimShady(true);
$item->addAttribute($extension_tag);
}
if ($application->isPrototype()) {
$prototype_tag = id(new PHUITagView())
->setName(pht('Prototype'))
->setIcon('fa-exclamation-circle')
->setColor(PHUITagView::COLOR_ORANGE)
->setType(PHUITagView::TYPE_SHADE)
->setSlimShady(true);
$item->addAttribute($prototype_tag);
}
if ($application->isDeprecated()) {
$deprecated_tag = id(new PHUITagView())
->setName(pht('Deprecated'))
->setIcon('fa-exclamation-triangle')
->setColor(PHUITagView::COLOR_RED)
->setType(PHUITagView::TYPE_SHADE)
->setSlimShady(true);
$item->addAttribute($deprecated_tag);
}
$item->addAttribute($description);
if ($application->getBaseURI() && $application->isInstalled()) {
$item->setHref($application->getBaseURI());
}
if (!$application->isInstalled()) {
$item->addAttribute(pht('Uninstalled'));
$item->setDisabled(true);
}
$list->addItem($item);
}
$results[] = $list;
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($results);
return $result;
}
}
diff --git a/src/applications/meta/typeahead/PhabricatorApplicationDatasource.php b/src/applications/meta/typeahead/PhabricatorApplicationDatasource.php
index acf9c8b32f..daf8494383 100644
--- a/src/applications/meta/typeahead/PhabricatorApplicationDatasource.php
+++ b/src/applications/meta/typeahead/PhabricatorApplicationDatasource.php
@@ -1,54 +1,54 @@
<?php
final class PhabricatorApplicationDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Applications');
}
public function getPlaceholderText() {
return pht('Type an application name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorApplicationsApplication';
+ return PhabricatorApplicationsApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
$applications = PhabricatorApplication::getAllInstalledApplications();
foreach ($applications as $application) {
$uri = $application->getTypeaheadURI();
if (!$uri) {
continue;
}
$is_installed = PhabricatorApplication::isClassInstalledForViewer(
get_class($application),
$viewer);
if (!$is_installed) {
continue;
}
$name = $application->getName().' '.$application->getShortDescription();
$img = 'phui-font-fa phui-icon-view '.$application->getIcon();
$results[] = id(new PhabricatorTypeaheadResult())
->setName($name)
->setURI($uri)
->setPHID($application->getPHID())
->setPriorityString($application->getName())
->setDisplayName($application->getName())
->setDisplayType($application->getShortDescription())
->setPriorityType('apps')
->setImageSprite('phabricator-search-icon '.$img)
->setIcon($application->getIcon())
->addAttribute($application->getShortDescription());
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/metamta/editor/PhabricatorMetaMTAApplicationEmailEditor.php b/src/applications/metamta/editor/PhabricatorMetaMTAApplicationEmailEditor.php
index 843e653039..601b3ffb89 100644
--- a/src/applications/metamta/editor/PhabricatorMetaMTAApplicationEmailEditor.php
+++ b/src/applications/metamta/editor/PhabricatorMetaMTAApplicationEmailEditor.php
@@ -1,169 +1,169 @@
<?php
final class PhabricatorMetaMTAApplicationEmailEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return pht('PhabricatorMetaMTAApplication');
+ return PhabricatorMetaMTAApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Application Emails');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS;
$types[] = PhabricatorMetaMTAApplicationEmailTransaction::TYPE_CONFIG;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS:
return $object->getAddress();
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_CONFIG:
$key = $xaction->getMetadataValue(
PhabricatorMetaMTAApplicationEmailTransaction::KEY_CONFIG);
return $object->getConfigValue($key);
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS:
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_CONFIG:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$new = $xaction->getNewValue();
switch ($xaction->getTransactionType()) {
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS:
$object->setAddress($new);
return;
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_CONFIG:
$key = $xaction->getMetadataValue(
PhabricatorMetaMTAApplicationEmailTransaction::KEY_CONFIG);
$object->setConfigValue($key, $new);
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS:
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_CONFIG:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS:
foreach ($xactions as $xaction) {
$email = $xaction->getNewValue();
if (!strlen($email)) {
// We'll deal with this below.
continue;
}
if (!PhabricatorUserEmail::isValidAddress($email)) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('Email address is not formatted properly.'));
continue;
}
$address = new PhutilEmailAddress($email);
if (PhabricatorMailUtil::isReservedAddress($address)) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Reserved'),
pht(
'This email address is reserved. Choose a different '.
'address.'));
continue;
}
// See T13234. Prevent use of user email addresses as application
// email addresses.
if (PhabricatorMailUtil::isUserAddress($address)) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('In Use'),
pht(
'This email address is already in use by a user. Choose '.
'a different address.'));
continue;
}
}
$missing = $this->validateIsEmptyTextField(
$object->getAddress(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('You must provide an email address.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
}
return $errors;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS,
pht('Duplicate'),
pht('This email address is already in use.'),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
}
diff --git a/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php b/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
index 94c13c9e0a..2bfe376084 100644
--- a/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
+++ b/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
@@ -1,71 +1,71 @@
<?php
final class PhabricatorMailOutboundMailHeraldAdapter
extends HeraldAdapter {
private $mail;
public function getAdapterApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
public function getAdapterContentDescription() {
return pht('Route outbound email.');
}
protected function initializeNewAdapter() {
$this->mail = $this->newObject();
}
protected function newObject() {
return new PhabricatorMetaMTAMail();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PhabricatorMetaMTAMail);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when outbound mail is being prepared for '.
'delivery.');
}
public function getObject() {
return $this->mail;
}
public function setObject(PhabricatorMetaMTAMail $mail) {
$this->mail = $mail;
return $this;
}
public function getAdapterContentName() {
return pht('Outbound Mail');
}
public function isSingleEventAdapter() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function getHeraldName() {
return pht('Mail %d', $this->getObject()->getID());
}
public function supportsWebhooks() {
return false;
}
}
diff --git a/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php b/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php
index 1436038fae..e8fd037ad2 100644
--- a/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php
+++ b/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhabricatorMetaMTAMailPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'MTAM';
public function getTypeName() {
return pht('MetaMTA Mail');
}
public function newObject() {
return new PhabricatorMetaMTAMail();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMetaMTAMailQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$mail = $objects[$phid];
$id = $mail->getID();
$name = pht('Mail %d', $id);
$handle
->setName($name)
->setURI('/mail/detail/'.$id.'/');
}
}
}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
index 9c0c5d941a..80c2f91c3a 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
@@ -1,111 +1,111 @@
<?php
final class PhabricatorMetaMTAApplicationEmailQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $addresses;
private $addressPrefix;
private $applicationPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAddresses(array $addresses) {
$this->addresses = $addresses;
return $this;
}
public function withAddressPrefix($prefix) {
$this->addressPrefix = $prefix;
return $this;
}
public function withApplicationPHIDs(array $phids) {
$this->applicationPHIDs = $phids;
return $this;
}
protected function loadPage() {
return $this->loadStandardPage(new PhabricatorMetaMTAApplicationEmail());
}
protected function willFilterPage(array $app_emails) {
$app_emails_map = mgroup($app_emails, 'getApplicationPHID');
$applications = id(new PhabricatorApplicationQuery())
->setViewer($this->getViewer())
->withPHIDs(array_keys($app_emails_map))
->execute();
$applications = mpull($applications, null, 'getPHID');
foreach ($app_emails_map as $app_phid => $app_emails_group) {
foreach ($app_emails_group as $app_email) {
$application = idx($applications, $app_phid);
if (!$application) {
unset($app_emails[$app_phid]);
continue;
}
$app_email->attachApplication($application);
}
}
return $app_emails;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->addresses !== null) {
$where[] = qsprintf(
$conn,
'appemail.address IN (%Ls)',
$this->addresses);
}
if ($this->addressPrefix !== null) {
$where[] = qsprintf(
$conn,
'appemail.address LIKE %>',
$this->addressPrefix);
}
if ($this->applicationPHIDs !== null) {
$where[] = qsprintf(
$conn,
'appemail.applicationPHID IN (%Ls)',
$this->applicationPHIDs);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'appemail.phid IN (%Ls)',
$this->phids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'appemail.id IN (%Ld)',
$this->ids);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'appemail';
}
public function getQueryApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
index b7dd3e5ee4..4cb1e2dedc 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorMetaMTAMailPropertiesQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function newResultObject() {
return new PhabricatorMetaMTAMailProperties();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
index d1f0235c90..dd7e961e24 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php
@@ -1,128 +1,128 @@
<?php
final class PhabricatorMetaMTAMailQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $actorPHIDs;
private $recipientPHIDs;
private $createdMin;
private $createdMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withActorPHIDs(array $phids) {
$this->actorPHIDs = $phids;
return $this;
}
public function withRecipientPHIDs(array $phids) {
$this->recipientPHIDs = $phids;
return $this;
}
public function withDateCreatedBetween($min, $max) {
$this->createdMin = $min;
$this->createdMax = $max;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'mail.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'mail.phid IN (%Ls)',
$this->phids);
}
if ($this->actorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'mail.actorPHID IN (%Ls)',
$this->actorPHIDs);
}
if ($this->createdMin !== null) {
$where[] = qsprintf(
$conn,
'mail.dateCreated >= %d',
$this->createdMin);
}
if ($this->createdMax !== null) {
$where[] = qsprintf(
$conn,
'mail.dateCreated <= %d',
$this->createdMax);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinRecipients()) {
$joins[] = qsprintf(
$conn,
'JOIN %T recipient
ON mail.phid = recipient.src
AND recipient.type = %d
AND recipient.dst IN (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST,
$this->recipientPHIDs);
}
return $joins;
}
private function shouldJoinRecipients() {
if ($this->recipientPHIDs === null) {
return false;
}
return true;
}
protected function getPrimaryTableAlias() {
return 'mail';
}
public function newResultObject() {
return new PhabricatorMetaMTAMail();
}
public function getQueryApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinRecipients()) {
if (count($this->recipientPHIDs) > 1) {
return true;
}
}
return parent::shouldGroupQueryResultRows();
}
}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php b/src/applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php
index df7774aae2..d3ae165e2a 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php
@@ -1,133 +1,133 @@
<?php
final class PhabricatorMetaMTAMailSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('MetaMTA Mails');
}
public function getApplicationClassName() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return new PhabricatorMetaMTAMailQuery();
}
protected function shouldShowOrderField() {
return false;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Actors'))
->setKey('actorPHIDs')
->setAliases(array('actor', 'actors')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Recipients'))
->setKey('recipientPHIDs')
->setAliases(array('recipient', 'recipients')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['actorPHIDs']) {
$query->withActorPHIDs($map['actorPHIDs']);
}
if ($map['recipientPHIDs']) {
$query->withRecipientPHIDs($map['recipientPHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/mail/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'inbox' => pht('Inbox'),
'outbox' => pht('Outbox'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$viewer = $this->requireViewer();
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'inbox':
return $query->setParameter(
'recipientPHIDs',
array($viewer->getPHID()));
case 'outbox':
return $query->setParameter(
'actorPHIDs',
array($viewer->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $objects,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($objects as $mail) {
$phids[] = $mail->getExpandedRecipientPHIDs();
}
return array_mergev($phids);
}
protected function renderResultList(
array $mails,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($mails, 'PhabricatorMetaMTAMail');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($mails as $mail) {
if ($mail->hasSensitiveContent()) {
$header = phutil_tag('em', array(), pht('Content Redacted'));
} else {
$header = $mail->getSubject();
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($mail)
->setEpoch($mail->getDateCreated())
->setObjectName(pht('Mail %d', $mail->getID()))
->setHeader($header)
->setHref($this->getURI('detail/'.$mail->getID().'/'));
$status = $mail->getStatus();
$status_name = PhabricatorMailOutboundStatus::getStatusName($status);
$status_icon = PhabricatorMailOutboundStatus::getStatusIcon($status);
$status_color = PhabricatorMailOutboundStatus::getStatusColor($status);
$item->setStatusIcon($status_icon.' '.$status_color, $status_name);
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setContent($list);
}
}
diff --git a/src/applications/metamta/typeahead/PhabricatorMetaMTAApplicationEmailDatasource.php b/src/applications/metamta/typeahead/PhabricatorMetaMTAApplicationEmailDatasource.php
index 62c1275c39..117d0771c3 100644
--- a/src/applications/metamta/typeahead/PhabricatorMetaMTAApplicationEmailDatasource.php
+++ b/src/applications/metamta/typeahead/PhabricatorMetaMTAApplicationEmailDatasource.php
@@ -1,52 +1,52 @@
<?php
final class PhabricatorMetaMTAApplicationEmailDatasource
extends PhabricatorTypeaheadDatasource {
public function isBrowsable() {
// TODO: Make this browsable.
return false;
}
public function getBrowseTitle() {
return pht('Browse Email Addresses');
}
public function getPlaceholderText() {
return pht('Type an application email address...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$emails = id(new PhabricatorMetaMTAApplicationEmailQuery())
->setViewer($viewer)
->withAddressPrefix($raw_query)
->setLimit($this->getLimit())
->execute();
if ($emails) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(mpull($emails, 'getPHID'))
->execute();
} else {
$handles = array();
}
$results = array();
foreach ($handles as $handle) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
->setPHID($handle->getPHID());
}
return $results;
}
}
diff --git a/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php b/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php
index 2e0e03bb3c..f9fa106e63 100644
--- a/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php
+++ b/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php
@@ -1,26 +1,26 @@
<?php
final class PhabricatorMetaMTAMailableDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Subscribers');
}
public function getPlaceholderText() {
return pht('Type a user, project, package, or mailing list name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
);
}
}
diff --git a/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php b/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php
index b5d82c9749..4d17a8b840 100644
--- a/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php
+++ b/src/applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php
@@ -1,30 +1,30 @@
<?php
final class PhabricatorMetaMTAMailableFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Subscribers');
}
public function getPlaceholderText() {
return pht(
'Type a username, project, mailing list, package, or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorViewerDatasource(),
new PhabricatorPeopleDatasource(),
new PhabricatorProjectMembersDatasource(),
new PhabricatorProjectDatasource(),
new PhabricatorOwnersPackageDatasource(),
new PhabricatorOwnersPackageOwnerDatasource(),
);
}
}
diff --git a/src/applications/notification/query/PhabricatorNotificationQuery.php b/src/applications/notification/query/PhabricatorNotificationQuery.php
index 2cd97f25c8..021d666b13 100644
--- a/src/applications/notification/query/PhabricatorNotificationQuery.php
+++ b/src/applications/notification/query/PhabricatorNotificationQuery.php
@@ -1,196 +1,196 @@
<?php
/**
* @task config Configuring the Query
* @task exec Query Execution
*/
final class PhabricatorNotificationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $userPHIDs;
private $keys;
private $unread;
/* -( Configuring the Query )---------------------------------------------- */
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
/**
* Filter results by read/unread status. Note that `true` means to return
* only unread notifications, while `false` means to return only //read//
* notifications. The default is `null`, which returns both.
*
* @param mixed True or false to filter results by read status. Null to remove
* the filter.
* @return this
* @task config
*/
public function withUnread($unread) {
$this->unread = $unread;
return $this;
}
/* -( Query Execution )---------------------------------------------------- */
protected function loadPage() {
$story_table = new PhabricatorFeedStoryData();
$notification_table = new PhabricatorFeedStoryNotification();
$conn = $story_table->establishConnection('r');
$data = queryfx_all(
$conn,
'SELECT story.*, notification.hasViewed FROM %R notification
JOIN %R story ON notification.chronologicalKey = story.chronologicalKey
%Q
ORDER BY notification.chronologicalKey DESC
%Q',
$notification_table,
$story_table,
$this->buildWhereClause($conn),
$this->buildLimitClause($conn));
return $data;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'notification.userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->unread !== null) {
$where[] = qsprintf(
$conn,
'notification.hasViewed = %d',
(int)!$this->unread);
}
if ($this->keys !== null) {
$where[] = qsprintf(
$conn,
'notification.chronologicalKey IN (%Ls)',
$this->keys);
}
return $where;
}
protected function willFilterPage(array $rows) {
// See T13623. The policy model here is outdated and awkward.
// Users may have notifications about objects they can no longer see.
// Two ways this can arise: destroy an object; or change an object's
// view policy to exclude a user.
// "PhabricatorFeedStory::loadAllFromRows()" does its own policy filtering.
// This doesn't align well with modern query sequencing, but we should be
// able to get away with it by loading here.
// See T13623. Although most queries for notifications return unique
// stories, this isn't a guarantee.
$story_map = ipull($rows, null, 'chronologicalKey');
$viewer = $this->getViewer();
$stories = PhabricatorFeedStory::loadAllFromRows($story_map, $viewer);
$stories = mpull($stories, null, 'getChronologicalKey');
$results = array();
foreach ($rows as $row) {
$story_key = $row['chronologicalKey'];
$has_viewed = $row['hasViewed'];
if (!isset($stories[$story_key])) {
// NOTE: We can't call "didRejectResult()" here because we don't have
// a policy object to pass.
continue;
}
$story = id(clone $stories[$story_key])
->setHasViewed($has_viewed);
if (!$story->isVisibleInNotifications()) {
continue;
}
$results[] = $story;
}
return $results;
}
protected function getDefaultOrderVector() {
return array('key');
}
public function getBuiltinOrders() {
return array(
'newest' => array(
'vector' => array('key'),
'name' => pht('Creation (Newest First)'),
'aliases' => array('created'),
),
'oldest' => array(
'vector' => array('-key'),
'name' => pht('Creation (Oldest First)'),
),
);
}
public function getOrderableColumns() {
return array(
'key' => array(
'table' => 'notification',
'column' => 'chronologicalKey',
'type' => 'string',
'unique' => true,
),
);
}
protected function applyExternalCursorConstraintsToQuery(
PhabricatorCursorPagedPolicyAwareQuery $subquery,
$cursor) {
$subquery
->withKeys(array($cursor))
->setLimit(1);
}
protected function newExternalCursorStringForResult($object) {
return $object->getChronologicalKey();
}
protected function newPagingMapFromPartialObject($object) {
return array(
'key' => $object['chronologicalKey'],
);
}
protected function getPrimaryTableAlias() {
return 'notification';
}
public function getQueryApplicationClass() {
- return 'PhabricatorNotificationsApplication';
+ return PhabricatorNotificationsApplication::class;
}
}
diff --git a/src/applications/notification/query/PhabricatorNotificationSearchEngine.php b/src/applications/notification/query/PhabricatorNotificationSearchEngine.php
index 4b56c5f5a1..353ebe9402 100644
--- a/src/applications/notification/query/PhabricatorNotificationSearchEngine.php
+++ b/src/applications/notification/query/PhabricatorNotificationSearchEngine.php
@@ -1,137 +1,137 @@
<?php
final class PhabricatorNotificationSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Notifications');
}
public function getApplicationClassName() {
- return 'PhabricatorNotificationsApplication';
+ return PhabricatorNotificationsApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'unread',
$this->readBoolFromRequest($request, 'unread'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorNotificationQuery())
->withUserPHIDs(array($this->requireViewer()->getPHID()));
if ($saved->getParameter('unread')) {
$query->withUnread(true);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$unread = $saved->getParameter('unread');
$form->appendChild(
id(new AphrontFormCheckboxControl())
->setLabel(pht('Unread'))
->addCheckbox(
'unread',
1,
pht('Show only unread notifications.'),
$unread));
}
protected function getURI($path) {
return '/notification/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Notifications'),
'unread' => pht('Unread Notifications'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'unread':
return $query->setParameter('unread', true);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $notifications,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($notifications, 'PhabricatorFeedStory');
$viewer = $this->requireViewer();
$image = id(new PHUIIconView())
->setIcon('fa-bell-o');
$button = id(new PHUIButtonView())
->setTag('a')
->addSigil('workflow')
->setColor(PHUIButtonView::GREY)
->setIcon($image)
->setText(pht('Mark All Read'));
switch ($query->getQueryKey()) {
case 'unread':
$header = pht('Unread Notifications');
$no_data = pht('You have no unread notifications.');
break;
default:
$header = pht('Notifications');
$no_data = pht('You have no notifications.');
break;
}
$clear_uri = id(new PhutilURI('/notification/clear/'));
if ($notifications) {
$builder = id(new PhabricatorNotificationBuilder($notifications))
->setUser($viewer);
$view = $builder->buildView();
$clear_uri->replaceQueryParam(
'chronoKey',
head($notifications)->getChronologicalKey());
} else {
$view = phutil_tag_div(
'phabricator-notification no-notifications',
$no_data);
$button->setDisabled(true);
}
$button->setHref((string)$clear_uri);
$view = id(new PHUIBoxView())
->addPadding(PHUI::PADDING_MEDIUM)
->addClass('phabricator-notification-list')
->appendChild($view);
$result = new PhabricatorApplicationSearchResultView();
$result->addAction($button);
$result->setContent($view);
return $result;
}
}
diff --git a/src/applications/nuance/editor/NuanceItemEditor.php b/src/applications/nuance/editor/NuanceItemEditor.php
index b41ca77563..4f2056d6ae 100644
--- a/src/applications/nuance/editor/NuanceItemEditor.php
+++ b/src/applications/nuance/editor/NuanceItemEditor.php
@@ -1,23 +1,23 @@
<?php
final class NuanceItemEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Nuance Items');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/nuance/editor/NuanceQueueEditEngine.php b/src/applications/nuance/editor/NuanceQueueEditEngine.php
index 12f5c7b517..2a49079a47 100644
--- a/src/applications/nuance/editor/NuanceQueueEditEngine.php
+++ b/src/applications/nuance/editor/NuanceQueueEditEngine.php
@@ -1,84 +1,84 @@
<?php
final class NuanceQueueEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'nuance.queue';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Nuance Queues');
}
public function getSummaryHeader() {
return pht('Edit Nuance Queue Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Nuance queues.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function newEditableObject() {
return NuanceQueue::initializeNewQueue();
}
protected function newObjectQuery() {
return new NuanceQueueQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Queue');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Queue');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Queue: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Queue');
}
protected function getObjectCreateShortText() {
return pht('Create Queue');
}
protected function getObjectName() {
return pht('Queue');
}
protected function getEditorURI() {
return '/nuance/queue/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/nuance/queue/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the queue.'))
->setTransactionType(NuanceQueueNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);
}
}
diff --git a/src/applications/nuance/editor/NuanceQueueEditor.php b/src/applications/nuance/editor/NuanceQueueEditor.php
index 2a18188f98..59abd3dd6d 100644
--- a/src/applications/nuance/editor/NuanceQueueEditor.php
+++ b/src/applications/nuance/editor/NuanceQueueEditor.php
@@ -1,23 +1,23 @@
<?php
final class NuanceQueueEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Nuance Queues');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/nuance/editor/NuanceSourceEditEngine.php b/src/applications/nuance/editor/NuanceSourceEditEngine.php
index eac751c3a5..882b9030fe 100644
--- a/src/applications/nuance/editor/NuanceSourceEditEngine.php
+++ b/src/applications/nuance/editor/NuanceSourceEditEngine.php
@@ -1,113 +1,113 @@
<?php
final class NuanceSourceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'nuance.source';
private $sourceDefinition;
public function setSourceDefinition(
NuanceSourceDefinition $source_definition) {
$this->sourceDefinition = $source_definition;
return $this;
}
public function getSourceDefinition() {
return $this->sourceDefinition;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Nuance Sources');
}
public function getSummaryHeader() {
return pht('Edit Nuance Source Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Nuance sources.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$definition = $this->getSourceDefinition();
if (!$definition) {
throw new PhutilInvalidStateException('setSourceDefinition');
}
return NuanceSource::initializeNewSource(
$viewer,
$definition);
}
protected function newObjectQuery() {
return new NuanceSourceQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Source');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Source');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Source: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Source');
}
protected function getObjectCreateShortText() {
return pht('Create Source');
}
protected function getObjectName() {
return pht('Source');
}
protected function getEditorURI() {
return '/nuance/source/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/nuance/source/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the source.'))
->setTransactionType(NuanceSourceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorDatasourceEditField())
->setKey('defaultQueue')
->setLabel(pht('Default Queue'))
->setDescription(pht('Default queue.'))
->setTransactionType(
NuanceSourceDefaultQueueTransaction::TRANSACTIONTYPE)
->setDatasource(new NuanceQueueDatasource())
->setSingleValue($object->getDefaultQueuePHID()),
);
}
}
diff --git a/src/applications/nuance/editor/NuanceSourceEditor.php b/src/applications/nuance/editor/NuanceSourceEditor.php
index b56b183f9e..d141dd0108 100644
--- a/src/applications/nuance/editor/NuanceSourceEditor.php
+++ b/src/applications/nuance/editor/NuanceSourceEditor.php
@@ -1,27 +1,27 @@
<?php
final class NuanceSourceEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Nuance Sources');
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
}
diff --git a/src/applications/nuance/phid/NuanceImportCursorPHIDType.php b/src/applications/nuance/phid/NuanceImportCursorPHIDType.php
index 9d1f816a71..bc28710d37 100644
--- a/src/applications/nuance/phid/NuanceImportCursorPHIDType.php
+++ b/src/applications/nuance/phid/NuanceImportCursorPHIDType.php
@@ -1,38 +1,38 @@
<?php
final class NuanceImportCursorPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'NUAC';
public function getTypeName() {
return pht('Import Cursor');
}
public function newObject() {
return new NuanceImportCursorData();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new NuanceImportCursorDataQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$item = $objects[$phid];
}
}
}
diff --git a/src/applications/nuance/phid/NuanceItemPHIDType.php b/src/applications/nuance/phid/NuanceItemPHIDType.php
index 771b398419..c9491776ca 100644
--- a/src/applications/nuance/phid/NuanceItemPHIDType.php
+++ b/src/applications/nuance/phid/NuanceItemPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class NuanceItemPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'NUAI';
public function getTypeName() {
return pht('Item');
}
public function newObject() {
return new NuanceItem();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new NuanceItemQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$item = $objects[$phid];
$handle->setName($item->getDisplayName());
$handle->setURI($item->getURI());
}
}
}
diff --git a/src/applications/nuance/phid/NuanceQueuePHIDType.php b/src/applications/nuance/phid/NuanceQueuePHIDType.php
index b51812320d..10cc4b707a 100644
--- a/src/applications/nuance/phid/NuanceQueuePHIDType.php
+++ b/src/applications/nuance/phid/NuanceQueuePHIDType.php
@@ -1,41 +1,41 @@
<?php
final class NuanceQueuePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'NUAQ';
public function getTypeName() {
return pht('Queue');
}
public function newObject() {
return new NuanceQueue();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new NuanceQueueQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$queue = $objects[$phid];
$handle->setName($queue->getName());
$handle->setURI($queue->getURI());
}
}
}
diff --git a/src/applications/nuance/phid/NuanceSourcePHIDType.php b/src/applications/nuance/phid/NuanceSourcePHIDType.php
index 774939bf29..17071684e8 100644
--- a/src/applications/nuance/phid/NuanceSourcePHIDType.php
+++ b/src/applications/nuance/phid/NuanceSourcePHIDType.php
@@ -1,41 +1,41 @@
<?php
final class NuanceSourcePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'NUAS';
public function getTypeName() {
return pht('Source');
}
public function newObject() {
return new NuanceSource();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new NuanceSourceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$source = $objects[$phid];
$handle->setName($source->getName());
$handle->setURI($source->getURI());
}
}
}
diff --git a/src/applications/nuance/query/NuanceItemSearchEngine.php b/src/applications/nuance/query/NuanceItemSearchEngine.php
index 0868d7551a..4b65c73394 100644
--- a/src/applications/nuance/query/NuanceItemSearchEngine.php
+++ b/src/applications/nuance/query/NuanceItemSearchEngine.php
@@ -1,98 +1,98 @@
<?php
final class NuanceItemSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getApplicationClassName() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getResultTypeDescription() {
return pht('Nuance Items');
}
public function newQuery() {
return new NuanceItemQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array(
);
}
protected function getURI($path) {
return '/nuance/item/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Items'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $items,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($items, 'NuanceItem');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($items as $item) {
$impl = $item->getImplementation();
$view = id(new PHUIObjectItemView())
->setObjectName(pht('Item %d', $item->getID()))
->setHeader($item->getDisplayName())
->setHref($item->getURI());
$view->addIcon(
$impl->getItemTypeDisplayIcon(),
$impl->getItemTypeDisplayName());
$queue = $item->getQueue();
if ($queue) {
$view->addAttribute(
phutil_tag(
'a',
array(
'href' => $queue->getURI(),
),
$queue->getName()));
} else {
$view->addAttribute(phutil_tag('em', array(), pht('Not in Queue')));
}
$list->addItem($view);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No items found.'));
return $result;
}
}
diff --git a/src/applications/nuance/query/NuanceQuery.php b/src/applications/nuance/query/NuanceQuery.php
index 1e72f5501e..b8e05f4dfe 100644
--- a/src/applications/nuance/query/NuanceQuery.php
+++ b/src/applications/nuance/query/NuanceQuery.php
@@ -1,9 +1,9 @@
<?php
abstract class NuanceQuery extends PhabricatorCursorPagedPolicyAwareQuery {
public function getQueryApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
}
diff --git a/src/applications/nuance/query/NuanceQueueSearchEngine.php b/src/applications/nuance/query/NuanceQueueSearchEngine.php
index 2f794c2a9c..7f3188b0c1 100644
--- a/src/applications/nuance/query/NuanceQueueSearchEngine.php
+++ b/src/applications/nuance/query/NuanceQueueSearchEngine.php
@@ -1,77 +1,77 @@
<?php
final class NuanceQueueSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getApplicationClassName() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getResultTypeDescription() {
return pht('Nuance Queues');
}
public function newQuery() {
return new NuanceQueueQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getURI($path) {
return '/nuance/queue/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Queues'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $queues,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($queues, 'NuanceQueue');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($queues as $queue) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Queue %d', $queue->getID()))
->setHeader($queue->getName())
->setHref($queue->getURI());
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No queues found.'));
return $result;
}
}
diff --git a/src/applications/nuance/query/NuanceSourceSearchEngine.php b/src/applications/nuance/query/NuanceSourceSearchEngine.php
index 44f131aa1b..7a1690eedf 100644
--- a/src/applications/nuance/query/NuanceSourceSearchEngine.php
+++ b/src/applications/nuance/query/NuanceSourceSearchEngine.php
@@ -1,89 +1,89 @@
<?php
final class NuanceSourceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getApplicationClassName() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function getResultTypeDescription() {
return pht('Nuance Sources');
}
public function newQuery() {
return new NuanceSourceQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for sources by name substring.')),
);
}
protected function getURI($path) {
return '/nuance/source/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Sources'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $sources,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($sources, 'NuanceSource');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($sources as $source) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Source %d', $source->getID()))
->setHeader($source->getName())
->setHref($source->getURI());
$item->addIcon('none', $source->getType());
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No sources found.'));
return $result;
}
}
diff --git a/src/applications/nuance/typeahead/NuanceQueueDatasource.php b/src/applications/nuance/typeahead/NuanceQueueDatasource.php
index 15b01fcecd..916dfaa75f 100644
--- a/src/applications/nuance/typeahead/NuanceQueueDatasource.php
+++ b/src/applications/nuance/typeahead/NuanceQueueDatasource.php
@@ -1,38 +1,38 @@
<?php
final class NuanceQueueDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Queues');
}
public function getPlaceholderText() {
return pht('Type a queue name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorNuanceApplication';
+ return PhabricatorNuanceApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
// TODO: Make this use real typeahead logic.
$query = new NuanceQueueQuery();
$queues = $this->executeQuery($query);
foreach ($queues as $queue) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($queue->getName())
->setURI('/nuance/queue/'.$queue->getID().'/')
->setPHID($queue->getPHID());
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/oauthserver/editor/PhabricatorOAuthServerEditEngine.php b/src/applications/oauthserver/editor/PhabricatorOAuthServerEditEngine.php
index ad47552c19..276863b7f3 100644
--- a/src/applications/oauthserver/editor/PhabricatorOAuthServerEditEngine.php
+++ b/src/applications/oauthserver/editor/PhabricatorOAuthServerEditEngine.php
@@ -1,100 +1,100 @@
<?php
final class PhabricatorOAuthServerEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'oauthserver.application';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('OAuth Applications');
}
public function getSummaryHeader() {
return pht('Edit OAuth Applications');
}
public function getSummaryText() {
return pht('This engine manages OAuth client applications.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
protected function newEditableObject() {
return PhabricatorOAuthServerClient::initializeNewClient(
$this->getViewer());
}
protected function newObjectQuery() {
return id(new PhabricatorOAuthServerClientQuery());
}
protected function getObjectCreateTitleText($object) {
return pht('Create OAuth Server');
}
protected function getObjectCreateButtonText($object) {
return pht('Create OAuth Server');
}
protected function getObjectEditTitleText($object) {
return pht('Edit OAuth Server: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Edit OAuth Server');
}
protected function getObjectCreateShortText() {
return pht('Create OAuth Server');
}
protected function getObjectName() {
return pht('OAuth Server');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorOAuthServerCreateClientsCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setIsRequired(true)
->setTransactionType(PhabricatorOAuthServerTransaction::TYPE_NAME)
->setDescription(pht('The name of the OAuth application.'))
->setConduitDescription(pht('Rename the application.'))
->setConduitTypeDescription(pht('New application name.'))
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('redirectURI')
->setLabel(pht('Redirect URI'))
->setIsRequired(true)
->setTransactionType(
PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI)
->setDescription(
pht('The redirect URI for OAuth handshakes.'))
->setConduitDescription(
pht(
'Change where this application redirects users to during OAuth '.
'handshakes.'))
->setConduitTypeDescription(
pht(
'New OAuth application redirect URI.'))
->setValue($object->getRedirectURI()),
);
}
}
diff --git a/src/applications/oauthserver/editor/PhabricatorOAuthServerEditor.php b/src/applications/oauthserver/editor/PhabricatorOAuthServerEditor.php
index 32b9d45054..27454e8777 100644
--- a/src/applications/oauthserver/editor/PhabricatorOAuthServerEditor.php
+++ b/src/applications/oauthserver/editor/PhabricatorOAuthServerEditor.php
@@ -1,146 +1,146 @@
<?php
final class PhabricatorOAuthServerEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
public function getEditorObjectsDescription() {
return pht('OAuth Applications');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorOAuthServerTransaction::TYPE_NAME;
$types[] = PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI;
$types[] = PhabricatorOAuthServerTransaction::TYPE_DISABLED;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOAuthServerTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI:
return $object->getRedirectURI();
case PhabricatorOAuthServerTransaction::TYPE_DISABLED:
return $object->getIsDisabled();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOAuthServerTransaction::TYPE_NAME:
case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI:
return $xaction->getNewValue();
case PhabricatorOAuthServerTransaction::TYPE_DISABLED:
return (int)$xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOAuthServerTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI:
$object->setRedirectURI($xaction->getNewValue());
return;
case PhabricatorOAuthServerTransaction::TYPE_DISABLED:
$object->setIsDisabled($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorOAuthServerTransaction::TYPE_NAME:
case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI:
case PhabricatorOAuthServerTransaction::TYPE_DISABLED:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorOAuthServerTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('OAuth applications must have a name.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI:
$missing = $this->validateIsEmptyTextField(
$object->getRedirectURI(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('OAuth applications must have a valid redirect URI.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else {
foreach ($xactions as $xaction) {
$redirect_uri = $xaction->getNewValue();
try {
$server = new PhabricatorOAuthServer();
$server->assertValidRedirectURI($redirect_uri);
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
}
}
}
break;
}
return $errors;
}
}
diff --git a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php
index b2fc1554fd..071fa5a8f6 100644
--- a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php
+++ b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorOAuthServerClientAuthorizationPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'OASA';
public function getTypeName() {
return pht('OAuth Authorization');
}
public function newObject() {
return new PhabricatorOAuthClientAuthorization();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorOAuthClientAuthorizationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$authorization = $objects[$phid];
$handle->setName(pht('Authorization %d', $authorization->getID()));
}
}
}
diff --git a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php
index 4d3d64738b..0fb623903b 100644
--- a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php
+++ b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorOAuthServerClientPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'OASC';
public function getTypeName() {
return pht('OAuth Application');
}
public function newObject() {
return new PhabricatorOAuthServerClient();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorOAuthServerClientQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$client = $objects[$phid];
$handle
->setName($client->getName())
->setURI($client->getURI());
}
}
}
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
index 63a62e8cd9..6a431daf3a 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
@@ -1,85 +1,85 @@
<?php
final class PhabricatorOAuthClientAuthorizationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $userPHIDs;
private $clientPHIDs;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withUserPHIDs(array $phids) {
$this->userPHIDs = $phids;
return $this;
}
public function withClientPHIDs(array $phids) {
$this->clientPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorOAuthClientAuthorization();
}
protected function willFilterPage(array $authorizations) {
$client_phids = mpull($authorizations, 'getClientPHID');
$clients = id(new PhabricatorOAuthServerClientQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($client_phids)
->execute();
$clients = mpull($clients, null, 'getPHID');
foreach ($authorizations as $key => $authorization) {
$client = idx($clients, $authorization->getClientPHID());
if (!$client) {
$this->didRejectResult($authorization);
unset($authorizations[$key]);
continue;
}
$authorization->attachClient($client);
}
return $authorizations;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->clientPHIDs !== null) {
$where[] = qsprintf(
$conn,
'clientPHID IN (%Ls)',
$this->clientPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
}
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php b/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
index 46fc514824..e500b3f42f 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorOAuthServerClientQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $creatorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorOAuthServerClient();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T client %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->creatorPHIDs) {
$where[] = qsprintf(
$conn,
'creatorPHID IN (%Ls)',
$this->creatorPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
}
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthServerClientSearchEngine.php b/src/applications/oauthserver/query/PhabricatorOAuthServerClientSearchEngine.php
index e07b1ea2c2..064ff34a26 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthServerClientSearchEngine.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthServerClientSearchEngine.php
@@ -1,107 +1,107 @@
<?php
final class PhabricatorOAuthServerClientSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('OAuth Clients');
}
public function getApplicationClassName() {
- return 'PhabricatorOAuthServerApplication';
+ return PhabricatorOAuthServerApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return id(new PhabricatorOAuthServerClientQuery());
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['creatorPHIDs']) {
$query->withCreatorPHIDs($map['creatorPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setAliases(array('creators'))
->setKey('creatorPHIDs')
->setConduitKey('creators')
->setLabel(pht('Creators'))
->setDescription(
pht('Search for applications created by particular users.')),
);
}
protected function getURI($path) {
return '/oauthserver/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['created'] = pht('Created');
}
$names['all'] = pht('All Applications');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'created':
return $query->setParameter(
'creatorPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $clients,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($clients, 'PhabricatorOAuthServerClient');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($clients as $client) {
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Application %d', $client->getID()))
->setHeader($client->getName())
->setHref($client->getViewURI())
->setObject($client);
if ($client->getIsDisabled()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No clients found.'));
return $result;
}
}
diff --git a/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php b/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php
index 416f2e38f2..7defcaacc0 100644
--- a/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php
+++ b/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php
@@ -1,199 +1,199 @@
<?php
final class PhabricatorOwnersPackageEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'owners.package';
public function getEngineName() {
return pht('Owners Packages');
}
public function getSummaryHeader() {
return pht('Configure Owners Package Forms');
}
public function getSummaryText() {
return pht('Configure forms for creating and editing packages in Owners.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
protected function newEditableObject() {
return PhabricatorOwnersPackage::initializeNewPackage($this->getViewer());
}
protected function newObjectQuery() {
return id(new PhabricatorOwnersPackageQuery())
->needPaths(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Package');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Package: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return pht('Package %d', $object->getID());
}
protected function getObjectCreateShortText() {
return pht('Create Package');
}
protected function getObjectName() {
return pht('Package');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
$paths_help = pht(<<<EOTEXT
When updating the paths for a package, pass a list of dictionaries like
this as the `value` for the transaction:
```lang=json, name="Example Paths Value"
[
{
"repositoryPHID": "PHID-REPO-1234",
"path": "/path/to/directory/",
"excluded": false
},
{
"repositoryPHID": "PHID-REPO-1234",
"path": "/another/example/path/",
"excluded": false
}
]
```
This transaction will set the paths to the list you provide, overwriting any
previous paths.
Generally, you will call `owners.search` first to get a list of current paths
(which are provided in the same format), make changes, then update them by
applying a transaction of this type.
EOTEXT
);
$autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap();
$autoreview_map = ipull($autoreview_map, 'name');
$dominion_map = PhabricatorOwnersPackage::getDominionOptionsMap();
$dominion_map = ipull($dominion_map, 'name');
$authority_map = PhabricatorOwnersPackage::getAuthorityOptionsMap();
$authority_map = ipull($authority_map, 'name');
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the package.'))
->setTransactionType(
PhabricatorOwnersPackageNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorDatasourceEditField())
->setKey('owners')
->setLabel(pht('Owners'))
->setDescription(pht('Users and projects which own the package.'))
->setTransactionType(
PhabricatorOwnersPackageOwnersTransaction::TRANSACTIONTYPE)
->setDatasource(new PhabricatorProjectOrUserDatasource())
->setIsCopyable(true)
->setValue($object->getOwnerPHIDs()),
id(new PhabricatorSelectEditField())
->setKey('dominion')
->setLabel(pht('Dominion'))
->setDescription(
pht('Change package dominion rules.'))
->setTransactionType(
PhabricatorOwnersPackageDominionTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getDominion())
->setOptions($dominion_map),
id(new PhabricatorSelectEditField())
->setKey('authority')
->setLabel(pht('Authority'))
->setDescription(
pht('Change package authority rules.'))
->setTransactionType(
PhabricatorOwnersPackageAuthorityTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getAuthorityMode())
->setOptions($authority_map),
id(new PhabricatorSelectEditField())
->setKey('autoReview')
->setLabel(pht('Auto Review'))
->setDescription(
pht(
'Automatically trigger reviews for commits affecting files in '.
'this package.'))
->setTransactionType(
PhabricatorOwnersPackageAutoreviewTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getAutoReview())
->setOptions($autoreview_map),
id(new PhabricatorSelectEditField())
->setKey('auditing')
->setLabel(pht('Auditing'))
->setDescription(
pht(
'Automatically trigger audits for commits affecting files in '.
'this package.'))
->setTransactionType(
PhabricatorOwnersPackageAuditingTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setValue($object->getAuditingState())
->setOptions(PhabricatorOwnersAuditRule::newSelectControlMap()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Human-readable description of the package.'))
->setTransactionType(
PhabricatorOwnersPackageDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setDescription(pht('Archive or enable the package.'))
->setTransactionType(
PhabricatorOwnersPackageStatusTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setValue($object->getStatus())
->setOptions($object->getStatusNameMap()),
id(new PhabricatorCheckboxesEditField())
->setKey('ignored')
->setLabel(pht('Ignored Attributes'))
->setDescription(pht('Ignore paths with any of these attributes.'))
->setTransactionType(
PhabricatorOwnersPackageIgnoredTransaction::TRANSACTIONTYPE)
->setValue(array_keys($object->getIgnoredPathAttributes()))
->setOptions(
array(
'generated' => pht('Ignore generated files (review only).'),
)),
id(new PhabricatorConduitEditField())
->setKey('paths.set')
->setLabel(pht('Paths'))
->setIsFormField(false)
->setTransactionType(
PhabricatorOwnersPackagePathsTransaction::TRANSACTIONTYPE)
->setConduitDescription(
pht('Overwrite existing package paths with new paths.'))
->setConduitTypeDescription(
pht('List of dictionaries, each describing a path.'))
->setConduitDocumentation($paths_help),
);
}
}
diff --git a/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
index 8885872706..797fe1ff44 100644
--- a/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
+++ b/src/applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php
@@ -1,74 +1,74 @@
<?php
final class PhabricatorOwnersPackageTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Owners Packages');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Package]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$this->requireActor()->getPHID(),
);
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return mpull($object->getOwners(), 'getUserPHID');
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new OwnersPackageReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject($name);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$detail_uri = PhabricatorEnv::getProductionURI($object->getURI());
$body->addLinkSection(
pht('PACKAGE DETAIL'),
$detail_uri);
return $body;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php b/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php
index fbff6a2103..a780c31709 100644
--- a/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php
+++ b/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorOwnersPackagePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'OPKG';
public function getTypeName() {
return pht('Owners Package');
}
public function getTypeIcon() {
return 'fa-shopping-bag';
}
public function newObject() {
return new PhabricatorOwnersPackage();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorOwnersPackageQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$package = $objects[$phid];
$monogram = $package->getMonogram();
$name = $package->getName();
$id = $package->getID();
$uri = $package->getURI();
$handle
->setName($monogram)
->setFullName("{$monogram}: {$name}")
->setCommandLineObjectName("{$monogram} {$name}")
->setMailStampName($monogram)
->setURI($uri);
if ($package->isArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^O\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorOwnersPackageQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
index a80b972548..71ba6ebd52 100644
--- a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
+++ b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
@@ -1,460 +1,460 @@
<?php
final class PhabricatorOwnersPackageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $ownerPHIDs;
private $authorityPHIDs;
private $repositoryPHIDs;
private $paths;
private $statuses;
private $authorityModes;
private $controlMap = array();
private $controlResults;
private $needPaths;
/**
* Query owner PHIDs exactly. This does not expand authorities, so a user
* PHID will not match projects the user is a member of.
*/
public function withOwnerPHIDs(array $phids) {
$this->ownerPHIDs = $phids;
return $this;
}
/**
* Query owner authority. This will expand authorities, so a user PHID will
* match both packages they own directly and packages owned by a project they
* are a member of.
*/
public function withAuthorityPHIDs(array $phids) {
$this->authorityPHIDs = $phids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withPaths(array $paths) {
$this->paths = $paths;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withControl($repository_phid, array $paths) {
if (empty($this->controlMap[$repository_phid])) {
$this->controlMap[$repository_phid] = array();
}
foreach ($paths as $path) {
$path = (string)$path;
$this->controlMap[$repository_phid][$path] = $path;
}
// We need to load paths to execute control queries.
$this->needPaths = true;
return $this;
}
public function withAuthorityModes(array $modes) {
$this->authorityModes = $modes;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new PhabricatorOwnersPackageNameNgrams(),
$ngrams);
}
public function needPaths($need_paths) {
$this->needPaths = $need_paths;
return $this;
}
public function newResultObject() {
return new PhabricatorOwnersPackage();
}
protected function willExecute() {
$this->controlResults = array();
}
protected function willFilterPage(array $packages) {
$package_ids = mpull($packages, 'getID');
$owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
'packageID IN (%Ld)',
$package_ids);
$owners = mgroup($owners, 'getPackageID');
foreach ($packages as $package) {
$package->attachOwners(idx($owners, $package->getID(), array()));
}
return $packages;
}
protected function didFilterPage(array $packages) {
$package_ids = mpull($packages, 'getID');
if ($this->needPaths) {
$paths = id(new PhabricatorOwnersPath())->loadAllWhere(
'packageID IN (%Ld)',
$package_ids);
$paths = mgroup($paths, 'getPackageID');
foreach ($packages as $package) {
$package->attachPaths(idx($paths, $package->getID(), array()));
}
}
if ($this->controlMap) {
foreach ($packages as $package) {
// If this package is archived, it's no longer a controlling package
// for any path. In particular, it can not force active packages with
// weak dominion to give up control.
if ($package->isArchived()) {
continue;
}
$this->controlResults[$package->getID()] = $package;
}
}
return $packages;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinOwnersTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T o ON o.packageID = p.id',
id(new PhabricatorOwnersOwner())->getTableName());
}
if ($this->shouldJoinPathTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T rpath ON rpath.packageID = p.id',
id(new PhabricatorOwnersPath())->getTableName());
}
return $joins;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'p.phid IN (%Ls)',
$this->phids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'p.id IN (%Ld)',
$this->ids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'rpath.repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->authorityPHIDs !== null) {
$authority_phids = $this->expandAuthority($this->authorityPHIDs);
$where[] = qsprintf(
$conn,
'o.userPHID IN (%Ls)',
$authority_phids);
}
if ($this->ownerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'o.userPHID IN (%Ls)',
$this->ownerPHIDs);
}
if ($this->paths !== null) {
$where[] = qsprintf(
$conn,
'rpath.pathIndex IN (%Ls)',
$this->getFragmentIndexesForPaths($this->paths));
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'p.status IN (%Ls)',
$this->statuses);
}
if ($this->controlMap) {
$clauses = array();
foreach ($this->controlMap as $repository_phid => $paths) {
$indexes = $this->getFragmentIndexesForPaths($paths);
$clauses[] = qsprintf(
$conn,
'(rpath.repositoryPHID = %s AND rpath.pathIndex IN (%Ls))',
$repository_phid,
$indexes);
}
$where[] = qsprintf($conn, '%LO', $clauses);
}
if ($this->authorityModes !== null) {
$where[] = qsprintf(
$conn,
'authorityMode IN (%Ls)',
$this->authorityModes);
}
return $where;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinOwnersTable()) {
return true;
}
if ($this->shouldJoinPathTable()) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'type' => 'string',
'unique' => true,
'reverse' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
);
}
public function getQueryApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
protected function getPrimaryTableAlias() {
return 'p';
}
private function shouldJoinOwnersTable() {
if ($this->ownerPHIDs !== null) {
return true;
}
if ($this->authorityPHIDs !== null) {
return true;
}
return false;
}
private function shouldJoinPathTable() {
if ($this->repositoryPHIDs !== null) {
return true;
}
if ($this->paths !== null) {
return true;
}
if ($this->controlMap) {
return true;
}
return false;
}
private function expandAuthority(array $phids) {
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withMemberPHIDs($phids)
->execute();
$project_phids = mpull($projects, 'getPHID');
return array_fuse($phids) + array_fuse($project_phids);
}
private function getFragmentsForPaths(array $paths) {
$fragments = array();
foreach ($paths as $path) {
foreach (PhabricatorOwnersPackage::splitPath($path) as $fragment) {
$fragments[$fragment] = $fragment;
}
}
return $fragments;
}
private function getFragmentIndexesForPaths(array $paths) {
$indexes = array();
foreach ($this->getFragmentsForPaths($paths) as $fragment) {
$indexes[] = PhabricatorHash::digestForIndex($fragment);
}
return $indexes;
}
/* -( Path Control )------------------------------------------------------- */
/**
* Get a list of all packages which control a path or its parent directories,
* ordered from weakest to strongest.
*
* The first package has the most specific claim on the path; the last
* package has the most general claim. Multiple packages may have claims of
* equal strength, so this ordering is primarily one of usability and
* convenience.
*
* @return list<PhabricatorOwnersPackage> List of controlling packages.
*/
public function getControllingPackagesForPath(
$repository_phid,
$path,
$ignore_dominion = false) {
$path = (string)$path;
if (!isset($this->controlMap[$repository_phid][$path])) {
throw new PhutilInvalidStateException('withControl');
}
if ($this->controlResults === null) {
throw new PhutilInvalidStateException('execute');
}
$packages = $this->controlResults;
$weak_dominion = PhabricatorOwnersPackage::DOMINION_WEAK;
$path_fragments = PhabricatorOwnersPackage::splitPath($path);
$fragment_count = count($path_fragments);
$matches = array();
foreach ($packages as $package_id => $package) {
$best_match = null;
$include = false;
$repository_paths = $package->getPathsForRepository($repository_phid);
foreach ($repository_paths as $package_path) {
$strength = $package_path->getPathMatchStrength(
$path_fragments,
$fragment_count);
if ($strength > $best_match) {
$best_match = $strength;
$include = !$package_path->getExcluded();
}
}
if ($best_match && $include) {
if ($ignore_dominion) {
$is_weak = false;
} else {
$is_weak = ($package->getDominion() == $weak_dominion);
}
$matches[$package_id] = array(
'strength' => $best_match,
'weak' => $is_weak,
'package' => $package,
);
}
}
// At each strength level, drop weak packages if there are also strong
// packages of the same strength.
$strength_map = igroup($matches, 'strength');
foreach ($strength_map as $strength => $package_list) {
$any_strong = false;
foreach ($package_list as $package_id => $package) {
if (!$package['weak']) {
$any_strong = true;
break;
}
}
if ($any_strong) {
foreach ($package_list as $package_id => $package) {
if ($package['weak']) {
unset($matches[$package_id]);
}
}
}
}
$matches = isort($matches, 'strength');
$matches = array_reverse($matches);
$strongest = null;
foreach ($matches as $package_id => $match) {
if ($strongest === null) {
$strongest = $match['strength'];
}
if ($match['strength'] === $strongest) {
continue;
}
if ($match['weak']) {
unset($matches[$package_id]);
}
}
return array_values(ipull($matches, 'package'));
}
}
diff --git a/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php b/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php
index 26889c0e7a..d0f2790ba7 100644
--- a/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php
+++ b/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php
@@ -1,179 +1,179 @@
<?php
final class PhabricatorOwnersPackageSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Owners Packages');
}
public function getApplicationClassName() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
public function newQuery() {
return new PhabricatorOwnersPackageQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Authority'))
->setKey('authorityPHIDs')
->setAliases(array('authority', 'authorities'))
->setConduitKey('owners')
->setDescription(
pht('Search for packages with specific owners.'))
->setDatasource(new PhabricatorProjectOrUserDatasource()),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('name')
->setDescription(pht('Search for packages by name substrings.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Repositories'))
->setKey('repositoryPHIDs')
->setConduitKey('repositories')
->setAliases(array('repository', 'repositories'))
->setDescription(
pht('Search for packages by included repositories.'))
->setDatasource(new DiffusionRepositoryDatasource()),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Paths'))
->setKey('paths')
->setAliases(array('path'))
->setDescription(
pht('Search for packages affecting specific paths.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setDescription(
pht('Search for active or archived packages.'))
->setOptions(
id(new PhabricatorOwnersPackage())
->getStatusNameMap()),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorityPHIDs']) {
$query->withAuthorityPHIDs($map['authorityPHIDs']);
}
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['paths']) {
$query->withPaths($map['paths']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if (strlen($map['name'])) {
$query->withNameNgrams($map['name']);
}
return $query;
}
protected function getURI($path) {
return '/owners/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authority'] = pht('Owned');
}
$names += array(
'active' => pht('Active Packages'),
'all' => pht('All Packages'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query->setParameter(
'statuses',
array(
PhabricatorOwnersPackage::STATUS_ACTIVE,
));
case 'authority':
return $query->setParameter(
'authorityPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $packages,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($packages, 'PhabricatorOwnersPackage');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($packages as $package) {
$id = $package->getID();
$item = id(new PHUIObjectItemView())
->setObject($package)
->setObjectName($package->getMonogram())
->setHeader($package->getName())
->setHref($package->getURI());
if ($package->isArchived()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No packages found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Package'))
->setHref('/owners/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht(
'Group sections of a codebase into packages for re-use in other '.
'applications, like Herald rules.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php b/src/applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php
index e93b3df7e9..8ad4db33f6 100644
--- a/src/applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php
+++ b/src/applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php
@@ -1,57 +1,57 @@
<?php
final class PhabricatorOwnersPackageDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Packages');
}
public function getPlaceholderText() {
return pht('Type a package name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$results = array();
$query = id(new PhabricatorOwnersPackageQuery())
->setOrder('name');
// If the user is querying by monogram explicitly, like "O123", do an ID
// search. Otherwise, do an ngram substring search.
if ($raw_query && preg_match('/^[oO]\d+\z/', $raw_query)) {
$id = trim($raw_query, 'oO');
$id = (int)$id;
$query->withIDs(array($id));
} else {
$query->withNameNgrams($raw_query);
}
$packages = $this->executeQuery($query);
foreach ($packages as $package) {
$name = $package->getName();
$monogram = $package->getMonogram();
$result = id(new PhabricatorTypeaheadResult())
->setName("{$monogram}: {$name}")
->setURI($package->getURI())
->setPHID($package->getPHID());
if ($package->isArchived()) {
$result->setClosed(pht('Archived'));
}
$results[] = $result;
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php b/src/applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php
index 2ad0512ee2..a8f4c12b19 100644
--- a/src/applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php
+++ b/src/applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php
@@ -1,25 +1,25 @@
<?php
final class PhabricatorOwnersPackageFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Packages');
}
public function getPlaceholderText() {
return pht('Type a package name or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorOwnersPackageDatasource(),
new PhabricatorOwnersPackageOwnerDatasource(),
);
}
}
diff --git a/src/applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php b/src/applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php
index 2a0b16e60f..ee60a85615 100644
--- a/src/applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php
+++ b/src/applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php
@@ -1,149 +1,149 @@
<?php
final class PhabricatorOwnersPackageOwnerDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Packages by Owner');
}
public function getPlaceholderText() {
return pht('Type packages(<user>) or packages(<project>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorOwnersApplication';
+ return PhabricatorOwnersApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
new PhabricatorProjectDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'packages' => array(
'name' => pht('Packages: ...'),
'arguments' => pht('owner'),
'summary' => pht("Find results in any of an owner's packages."),
'description' => pht(
"This function allows you to find results associated with any ".
"of the packages a specified user or project is an owner of. ".
"For example, this will find results associated with all of ".
"the projects `%s` owns:\n\n%s\n\n",
'alincoln',
'> packages(alincoln)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setColor(null)
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setPHID('packages('.$result->getPHID().')')
->setDisplayName(pht('Packages: %s', $result->getDisplayName()))
->setName($result->getName().' packages');
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$owner_phids = array();
foreach ($phids as $key => $phid) {
switch (phid_get_type($phid)) {
case PhabricatorPeopleUserPHIDType::TYPECONST:
case PhabricatorProjectProjectPHIDType::TYPECONST:
$owner_phids[] = $phid;
unset($phids[$key]);
break;
}
}
if ($owner_phids) {
$packages = id(new PhabricatorOwnersPackageQuery())
->setViewer($this->getViewer())
->withOwnerPHIDs($owner_phids)
->execute();
foreach ($packages as $package) {
$phids[] = $package->getPHID();
}
}
return $phids;
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht('Packages: Invalid Owner'));
} else {
$token
->setIcon('fa-asterisk')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setKey('packages('.$token->getKey().')')
->setValue(pht('Packages: %s', $token->getValue()));
}
}
return $tokens;
}
private function resolvePHIDs(array $phids) {
// TODO: It would be nice for this to handle `packages(#project)` from a
// query string or eventually via Conduit. This could also share code with
// PhabricatorProjectLogicalUserDatasource.
$usernames = array();
foreach ($phids as $key => $phid) {
switch (phid_get_type($phid)) {
case PhabricatorPeopleUserPHIDType::TYPECONST:
case PhabricatorProjectProjectPHIDType::TYPECONST:
break;
default:
$usernames[$key] = $phid;
break;
}
}
if ($usernames) {
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withUsernames($usernames)
->execute();
$users = mpull($users, null, 'getUsername');
foreach ($usernames as $key => $username) {
$user = idx($users, $username);
if ($user) {
$phids[$key] = $user->getPHID();
}
}
}
return $phids;
}
}
diff --git a/src/applications/packages/editor/PhabricatorPackagesEditEngine.php b/src/applications/packages/editor/PhabricatorPackagesEditEngine.php
index 1ba71d7274..3bd4d29395 100644
--- a/src/applications/packages/editor/PhabricatorPackagesEditEngine.php
+++ b/src/applications/packages/editor/PhabricatorPackagesEditEngine.php
@@ -1,14 +1,14 @@
<?php
abstract class PhabricatorPackagesEditEngine
extends PhabricatorEditEngine {
public function isEngineConfigurable() {
return false;
}
public function getEngineApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
}
diff --git a/src/applications/packages/editor/PhabricatorPackagesEditor.php b/src/applications/packages/editor/PhabricatorPackagesEditor.php
index 492b14643a..10d4c608a3 100644
--- a/src/applications/packages/editor/PhabricatorPackagesEditor.php
+++ b/src/applications/packages/editor/PhabricatorPackagesEditor.php
@@ -1,20 +1,20 @@
<?php
abstract class PhabricatorPackagesEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
protected function supportsSearch() {
return true;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
}
diff --git a/src/applications/packages/phid/PhabricatorPackagesPackagePHIDType.php b/src/applications/packages/phid/PhabricatorPackagesPackagePHIDType.php
index 6f8e982c81..3f8ba658c9 100644
--- a/src/applications/packages/phid/PhabricatorPackagesPackagePHIDType.php
+++ b/src/applications/packages/phid/PhabricatorPackagesPackagePHIDType.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorPackagesPackagePHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'PPAK';
public function getTypeName() {
return pht('Package');
}
public function newObject() {
return new PhabricatorPackagesPackage();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPackagesPackageQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$package = $objects[$phid];
$name = $package->getName();
$uri = $package->getURI();
$handle
->setName($name)
->setURI($uri);
}
}
}
diff --git a/src/applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php b/src/applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php
index f746ddce22..c63f27652c 100644
--- a/src/applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php
+++ b/src/applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorPackagesPublisherPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'PPUB';
public function getTypeName() {
return pht('Package Publisher');
}
public function newObject() {
return new PhabricatorPackagesPublisher();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPackagesPublisherQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$publisher = $objects[$phid];
$name = $publisher->getName();
$uri = $publisher->getURI();
$handle
->setName($name)
->setURI($uri);
}
}
}
diff --git a/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php b/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
index 203cca20e0..ffad58ffcf 100644
--- a/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
+++ b/src/applications/packages/phid/PhabricatorPackagesVersionPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorPackagesVersionPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'PVER';
public function getTypeName() {
return pht('Version');
}
public function newObject() {
return new PhabricatorPackagesVersion();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPackagesVersionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$version = $objects[$phid];
$name = $version->getName();
$uri = $version->getURI();
$handle
->setName($name)
->setURI($uri);
}
}
}
diff --git a/src/applications/packages/query/PhabricatorPackagesPackageSearchEngine.php b/src/applications/packages/query/PhabricatorPackagesPackageSearchEngine.php
index 817321dec1..5c8c465085 100644
--- a/src/applications/packages/query/PhabricatorPackagesPackageSearchEngine.php
+++ b/src/applications/packages/query/PhabricatorPackagesPackageSearchEngine.php
@@ -1,93 +1,93 @@
<?php
final class PhabricatorPackagesPackageSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Packages');
}
public function getApplicationClassName() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
public function newQuery() {
return id(new PhabricatorPackagesPackageQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['publisherPHIDs']) {
$query->withPublisherPHIDs($map['publisherPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for packages by name substring.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Publishers'))
->setKey('publisherPHIDs')
->setAliases(array('publisherPHID', 'publisher', 'publishers'))
->setDatasource(new PhabricatorPackagesPublisherDatasource())
->setDescription(pht('Search for packages by publisher.')),
);
}
protected function getURI($path) {
return '/packages/package/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Packages'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $packages,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($packages, 'PhabricatorPackagesPackage');
$viewer = $this->requireViewer();
$list = id(new PhabricatorPackagesPackageListView())
->setViewer($viewer)
->setPackages($packages)
->newListView();
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No packages found.'));
}
}
diff --git a/src/applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php b/src/applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php
index be7b83f5fc..03e2e968a4 100644
--- a/src/applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php
+++ b/src/applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php
@@ -1,84 +1,84 @@
<?php
final class PhabricatorPackagesPublisherSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Package Publishers');
}
public function getApplicationClassName() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
public function newQuery() {
return id(new PhabricatorPackagesPublisherQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for publishers by name substring.')),
);
}
protected function getURI($path) {
return '/packages/publisher/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Publishers'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $publishers,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($publishers, 'PhabricatorPackagesPublisher');
$viewer = $this->requireViewer();
$list = id(new PhabricatorPackagesPublisherListView())
->setViewer($viewer)
->setPublishers($publishers)
->newListView();
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No publishers found.'));
}
}
diff --git a/src/applications/packages/query/PhabricatorPackagesQuery.php b/src/applications/packages/query/PhabricatorPackagesQuery.php
index e7e882bdad..1ce60d9486 100644
--- a/src/applications/packages/query/PhabricatorPackagesQuery.php
+++ b/src/applications/packages/query/PhabricatorPackagesQuery.php
@@ -1,38 +1,38 @@
<?php
abstract class PhabricatorPackagesQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
public function getQueryApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
protected function buildFullKeyClauseParts(
AphrontDatabaseConnection $conn,
array $full_keys) {
$parts = array();
foreach ($full_keys as $full_key) {
$key_parts = explode('/', $full_key, 2);
if (count($key_parts) != 2) {
continue;
}
$parts[] = qsprintf(
$conn,
'(u.publisherKey = %s AND p.packageKey = %s)',
$key_parts[0],
$key_parts[1]);
}
// If none of the full keys we were provided were valid, we don't
// match any results.
if (!$parts) {
throw new PhabricatorEmptyQueryException();
}
return qsprintf($conn, '%LO', $parts);
}
}
diff --git a/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php b/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
index b3592ffd70..464b423ee4 100644
--- a/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
+++ b/src/applications/packages/query/PhabricatorPackagesVersionSearchEngine.php
@@ -1,92 +1,92 @@
<?php
final class PhabricatorPackagesVersionSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Package Versions');
}
public function getApplicationClassName() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
public function newQuery() {
return id(new PhabricatorPackagesVersionQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['match'] !== null) {
$query->withNameNgrams($map['match']);
}
if ($map['packagePHIDs']) {
$query->withPackagePHIDs($map['packagePHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for versions by name substring.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Packages'))
->setKey('packagePHIDs')
->setAliases(array('packagePHID', 'package', 'packages'))
->setDatasource(new PhabricatorPackagesPackageDatasource())
->setDescription(pht('Search for versions by package.')),
);
}
protected function getURI($path) {
return '/packages/version/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Versions'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $versions,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($versions, 'PhabricatorPackagesVersion');
$viewer = $this->requireViewer();
$list = id(new PhabricatorPackagesVersionListView())
->setViewer($viewer)
->setVersions($versions)
->newListView();
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No versions found.'));
}
}
diff --git a/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php b/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
index 9b2296db12..f9e88c7ac0 100644
--- a/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
+++ b/src/applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php
@@ -1,35 +1,35 @@
<?php
final class PhabricatorPackagesPackageDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Packages');
}
public function getPlaceholderText() {
return pht('Type a package name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$package_query = id(new PhabricatorPackagesPackageQuery());
$packages = $this->executeQuery($package_query);
$results = array();
foreach ($packages as $package) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($package->getName())
->setPHID($package->getPHID());
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php b/src/applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php
index e8ca7d4c7f..d8fe5ffc52 100644
--- a/src/applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php
+++ b/src/applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php
@@ -1,35 +1,35 @@
<?php
final class PhabricatorPackagesPublisherDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Package Publishers');
}
public function getPlaceholderText() {
return pht('Type a publisher name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPackagesApplication';
+ return PhabricatorPackagesApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
$publisher_query = id(new PhabricatorPackagesPublisherQuery());
$publishers = $this->executeQuery($publisher_query);
$results = array();
foreach ($publishers as $publisher) {
$results[] = id(new PhabricatorTypeaheadResult())
->setName($publisher->getName())
->setPHID($publisher->getPHID());
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
index 1e23c874cf..ead8658543 100644
--- a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
+++ b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
@@ -1,34 +1,34 @@
<?php
final class PassphraseCredentialTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPassphraseApplication';
+ return PhabricatorPassphraseApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Passphrase Credentials');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this credential.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/passphrase/phid/PassphraseCredentialPHIDType.php b/src/applications/passphrase/phid/PassphraseCredentialPHIDType.php
index 25681906e3..76fb537554 100644
--- a/src/applications/passphrase/phid/PassphraseCredentialPHIDType.php
+++ b/src/applications/passphrase/phid/PassphraseCredentialPHIDType.php
@@ -1,76 +1,76 @@
<?php
final class PassphraseCredentialPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CDTL';
public function getTypeName() {
return pht('Passphrase Credential');
}
public function newObject() {
return new PassphraseCredential();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPassphraseApplication';
+ return PhabricatorPassphraseApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PassphraseCredentialQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$credential = $objects[$phid];
$id = $credential->getID();
$name = $credential->getName();
$handle->setName("K{$id}");
$handle->setFullName("K{$id} {$name}");
$handle->setURI("/K{$id}");
if ($credential->getIsDestroyed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^K\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PassphraseCredentialQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/passphrase/query/PassphraseCredentialQuery.php b/src/applications/passphrase/query/PassphraseCredentialQuery.php
index 98ae9429a8..33a6947324 100644
--- a/src/applications/passphrase/query/PassphraseCredentialQuery.php
+++ b/src/applications/passphrase/query/PassphraseCredentialQuery.php
@@ -1,165 +1,165 @@
<?php
final class PassphraseCredentialQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $credentialTypes;
private $providesTypes;
private $isDestroyed;
private $allowConduit;
private $nameContains;
private $needSecrets;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCredentialTypes(array $credential_types) {
$this->credentialTypes = $credential_types;
return $this;
}
public function withProvidesTypes(array $provides_types) {
$this->providesTypes = $provides_types;
return $this;
}
public function withIsDestroyed($destroyed) {
$this->isDestroyed = $destroyed;
return $this;
}
public function withAllowConduit($allow_conduit) {
$this->allowConduit = $allow_conduit;
return $this;
}
public function withNameContains($name_contains) {
$this->nameContains = $name_contains;
return $this;
}
public function needSecrets($need_secrets) {
$this->needSecrets = $need_secrets;
return $this;
}
public function newResultObject() {
return new PassphraseCredential();
}
protected function willFilterPage(array $page) {
if ($this->needSecrets) {
$secret_ids = mpull($page, 'getSecretID');
$secret_ids = array_filter($secret_ids);
$secrets = array();
if ($secret_ids) {
$secret_objects = id(new PassphraseSecret())->loadAllWhere(
'id IN (%Ld)',
$secret_ids);
foreach ($secret_objects as $secret) {
$secret_data = $secret->getSecretData();
$secrets[$secret->getID()] = new PhutilOpaqueEnvelope($secret_data);
}
}
foreach ($page as $key => $credential) {
$secret_id = $credential->getSecretID();
if (!$secret_id) {
$credential->attachSecret(null);
} else if (isset($secrets[$secret_id])) {
$credential->attachSecret($secrets[$secret_id]);
} else {
unset($page[$key]);
}
}
}
foreach ($page as $key => $credential) {
$type = PassphraseCredentialType::getTypeByConstant(
$credential->getCredentialType());
if (!$type) {
unset($page[$key]);
continue;
}
$credential->attachImplementation(clone $type);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'c.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'c.phid IN (%Ls)',
$this->phids);
}
if ($this->credentialTypes !== null) {
$where[] = qsprintf(
$conn,
'c.credentialType in (%Ls)',
$this->credentialTypes);
}
if ($this->providesTypes !== null) {
$where[] = qsprintf(
$conn,
'c.providesType IN (%Ls)',
$this->providesTypes);
}
if ($this->isDestroyed !== null) {
$where[] = qsprintf(
$conn,
'c.isDestroyed = %d',
(int)$this->isDestroyed);
}
if ($this->allowConduit !== null) {
$where[] = qsprintf(
$conn,
'c.allowConduit = %d',
(int)$this->allowConduit);
}
if (phutil_nonempty_string($this->nameContains)) {
$where[] = qsprintf(
$conn,
'LOWER(c.name) LIKE %~',
phutil_utf8_strtolower($this->nameContains));
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPassphraseApplication';
+ return PhabricatorPassphraseApplication::class;
}
protected function getPrimaryTableAlias() {
return 'c';
}
}
diff --git a/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php b/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php
index 971094afc4..24cc6609ff 100644
--- a/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php
+++ b/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php
@@ -1,133 +1,133 @@
<?php
final class PassphraseCredentialSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Passphrase Credentials');
}
public function getApplicationClassName() {
- return 'PhabricatorPassphraseApplication';
+ return PhabricatorPassphraseApplication::class;
}
public function newQuery() {
return new PassphraseCredentialQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Status'))
->setKey('isDestroyed')
->setOptions(
pht('Show All'),
pht('Show Only Destroyed Credentials'),
pht('Show Only Active Credentials')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('name'),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['isDestroyed'] !== null) {
$query->withIsDestroyed($map['isDestroyed']);
}
if (strlen($map['name'])) {
$query->withNameContains($map['name']);
}
return $query;
}
protected function getURI($path) {
return '/passphrase/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'active' => pht('Active Credentials'),
'all' => pht('All Credentials'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query->setParameter('isDestroyed', false);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $credentials,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($credentials, 'PassphraseCredential');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($credentials as $credential) {
$item = id(new PHUIObjectItemView())
->setObjectName('K'.$credential->getID())
->setHeader($credential->getName())
->setHref('/K'.$credential->getID())
->setObject($credential);
$item->addAttribute(
pht('Login: %s', $credential->getUsername()));
if ($credential->getIsDestroyed()) {
$item->addIcon('fa-ban', pht('Destroyed'));
$item->setDisabled(true);
}
$type = PassphraseCredentialType::getTypeByConstant(
$credential->getCredentialType());
if ($type) {
$item->addIcon('fa-wrench', $type->getCredentialTypeName());
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No credentials found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Credential'))
->setHref('/passphrase/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Credential management and general storage of shared secrets.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/paste/editor/PhabricatorPasteEditEngine.php b/src/applications/paste/editor/PhabricatorPasteEditEngine.php
index 146565e87e..31859e7530 100644
--- a/src/applications/paste/editor/PhabricatorPasteEditEngine.php
+++ b/src/applications/paste/editor/PhabricatorPasteEditEngine.php
@@ -1,116 +1,116 @@
<?php
final class PhabricatorPasteEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'paste.paste';
public function getEngineName() {
return pht('Pastes');
}
public function getSummaryHeader() {
return pht('Configure Paste Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Paste.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
protected function newEditableObject() {
return PhabricatorPaste::initializeNewPaste($this->getViewer());
}
protected function newObjectQuery() {
return id(new PhabricatorPasteQuery())
->needRawContent(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Paste');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Paste: %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
protected function getObjectCreateShortText() {
return pht('Create Paste');
}
protected function getObjectName() {
return pht('Paste');
}
protected function getCommentViewHeaderText($object) {
return pht('Eat Paste');
}
protected function getCommentViewButtonText($object) {
return pht('Nom Nom Nom Nom Nom');
}
protected function getObjectViewURI($object) {
return '/P'.$object->getID();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
->setTransactionType(PhabricatorPasteTitleTransaction::TRANSACTIONTYPE)
->setDescription(pht('The title of the paste.'))
->setConduitDescription(pht('Retitle the paste.'))
->setConduitTypeDescription(pht('New paste title.'))
->setValue($object->getTitle()),
id(new PhabricatorDatasourceEditField())
->setKey('language')
->setLabel(pht('Language'))
->setTransactionType(
PhabricatorPasteLanguageTransaction::TRANSACTIONTYPE)
->setAliases(array('lang'))
->setIsCopyable(true)
->setDatasource(new PasteLanguageSelectDatasource())
->setDescription(
pht(
'Language used for syntax highlighting. By default, inferred '.
'from the title.'))
->setConduitDescription(
pht('Change language used for syntax highlighting.'))
->setConduitTypeDescription(pht('New highlighting language.'))
->setSingleValue($object->getLanguage()),
id(new PhabricatorTextAreaEditField())
->setKey('text')
->setLabel(pht('Text'))
->setTransactionType(
PhabricatorPasteContentTransaction::TRANSACTIONTYPE)
->setMonospaced(true)
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
->setDescription(pht('The main body text of the paste.'))
->setConduitDescription(pht('Change the paste content.'))
->setConduitTypeDescription(pht('New body content.'))
->setValue($object->getRawContent()),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(
PhabricatorPasteStatusTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setOptions(PhabricatorPaste::getStatusNameMap())
->setDescription(pht('Active or archived status.'))
->setConduitDescription(pht('Active or archive the paste.'))
->setConduitTypeDescription(pht('New paste status constant.'))
->setValue($object->getStatus()),
);
}
}
diff --git a/src/applications/paste/editor/PhabricatorPasteEditor.php b/src/applications/paste/editor/PhabricatorPasteEditor.php
index b120f58a57..1af612b08e 100644
--- a/src/applications/paste/editor/PhabricatorPasteEditor.php
+++ b/src/applications/paste/editor/PhabricatorPasteEditor.php
@@ -1,123 +1,123 @@
<?php
final class PhabricatorPasteEditor
extends PhabricatorApplicationTransactionEditor {
private $newPasteTitle;
public function getNewPasteTitle() {
return $this->newPasteTitle;
}
public function getEditorApplicationClass() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Pastes');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this paste.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
return $types;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$new_title = $object->getTitle();
foreach ($xactions as $xaction) {
$type = $xaction->getTransactionType();
if ($type === PhabricatorPasteTitleTransaction::TRANSACTIONTYPE) {
$new_title = $xaction->getNewValue();
}
}
$this->newPasteTitle = $new_title;
return parent::expandTransactions($object, $xactions);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
if ($this->getIsNewObject()) {
return false;
}
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Paste]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->getActingAsPHID(),
);
}
public function getMailTagsMap() {
return array(
PhabricatorPasteTransaction::MAILTAG_CONTENT =>
pht('Paste title, language or text changes.'),
PhabricatorPasteTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a paste.'),
PhabricatorPasteTransaction::MAILTAG_OTHER =>
pht('Other paste activity not listed above occurs.'),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PasteReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject("P{$id}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('PASTE DETAIL'),
PhabricatorEnv::getProductionURI('/P'.$object->getID()));
return $body;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php
index d08d52e2e1..b04553aa14 100644
--- a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php
+++ b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorPastePastePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PSTE';
public function getTypeName() {
return pht('Paste');
}
public function newObject() {
return new PhabricatorPaste();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPasteQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$paste = $objects[$phid];
$id = $paste->getID();
$name = $paste->getFullName();
$handle->setName("P{$id}");
$handle->setFullName($name);
$handle->setURI("/P{$id}");
}
}
public function canLoadNamedObject($name) {
return preg_match('/^P\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorPasteQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/paste/query/PhabricatorPasteQuery.php b/src/applications/paste/query/PhabricatorPasteQuery.php
index e841bff300..bcc1560700 100644
--- a/src/applications/paste/query/PhabricatorPasteQuery.php
+++ b/src/applications/paste/query/PhabricatorPasteQuery.php
@@ -1,396 +1,396 @@
<?php
final class PhabricatorPasteQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $parentPHIDs;
private $needContent;
private $needRawContent;
private $needSnippets;
private $languages;
private $includeNoLanguage;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withParentPHIDs(array $phids) {
$this->parentPHIDs = $phids;
return $this;
}
public function needContent($need_content) {
$this->needContent = $need_content;
return $this;
}
public function needRawContent($need_raw_content) {
$this->needRawContent = $need_raw_content;
return $this;
}
public function needSnippets($need_snippets) {
$this->needSnippets = $need_snippets;
return $this;
}
public function withLanguages(array $languages) {
$this->includeNoLanguage = false;
foreach ($languages as $key => $language) {
if ($language === null) {
$languages[$key] = '';
continue;
}
}
$this->languages = $languages;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhabricatorPaste();
}
protected function didFilterPage(array $pastes) {
if ($this->needRawContent) {
$pastes = $this->loadRawContent($pastes);
}
if ($this->needContent) {
$pastes = $this->loadContent($pastes);
}
if ($this->needSnippets) {
$pastes = $this->loadSnippets($pastes);
}
return $pastes;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'paste.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'paste.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'paste.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->parentPHIDs !== null) {
$where[] = qsprintf(
$conn,
'paste.parentPHID IN (%Ls)',
$this->parentPHIDs);
}
if ($this->languages !== null) {
$where[] = qsprintf(
$conn,
'paste.language IN (%Ls)',
$this->languages);
}
if ($this->dateCreatedAfter !== null) {
$where[] = qsprintf(
$conn,
'paste.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore !== null) {
$where[] = qsprintf(
$conn,
'paste.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'paste.status IN (%Ls)',
$this->statuses);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'paste';
}
private function getContentCacheKey(PhabricatorPaste $paste) {
return implode(
':',
array(
'P'.$paste->getID(),
$paste->getFilePHID(),
$paste->getLanguage(),
PhabricatorHash::digestForIndex($paste->getTitle()),
));
}
private function getSnippetCacheKey(PhabricatorPaste $paste) {
return implode(
':',
array(
'P'.$paste->getID(),
$paste->getFilePHID(),
$paste->getLanguage(),
'snippet',
'v2.1',
PhabricatorHash::digestForIndex($paste->getTitle()),
));
}
private function loadRawContent(array $pastes) {
$file_phids = mpull($pastes, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($pastes as $key => $paste) {
$file = idx($files, $paste->getFilePHID());
if (!$file) {
unset($pastes[$key]);
continue;
}
try {
$paste->attachRawContent($file->loadFileData());
} catch (Exception $ex) {
// We can hit various sorts of file storage issues here. Just drop the
// paste if the file is dead.
unset($pastes[$key]);
continue;
}
}
return $pastes;
}
private function loadContent(array $pastes) {
$cache = new PhabricatorKeyValueDatabaseCache();
$cache = new PhutilKeyValueCacheProfiler($cache);
$cache->setProfiler(PhutilServiceProfiler::getInstance());
$keys = array();
foreach ($pastes as $paste) {
$keys[] = $this->getContentCacheKey($paste);
}
$caches = $cache->getKeys($keys);
$need_raw = array();
$have_cache = array();
foreach ($pastes as $paste) {
$key = $this->getContentCacheKey($paste);
if (isset($caches[$key])) {
$paste->attachContent(phutil_safe_html($caches[$key]));
$have_cache[$paste->getPHID()] = true;
} else {
$need_raw[$key] = $paste;
}
}
if (!$need_raw) {
return $pastes;
}
$write_data = array();
$have_raw = $this->loadRawContent($need_raw);
$have_raw = mpull($have_raw, null, 'getPHID');
foreach ($pastes as $key => $paste) {
$paste_phid = $paste->getPHID();
if (isset($have_cache[$paste_phid])) {
continue;
}
if (empty($have_raw[$paste_phid])) {
unset($pastes[$key]);
continue;
}
$content = $this->buildContent($paste);
$paste->attachContent($content);
$write_data[$this->getContentCacheKey($paste)] = (string)$content;
}
if ($write_data) {
$cache->setKeys($write_data);
}
return $pastes;
}
private function loadSnippets(array $pastes) {
$cache = new PhabricatorKeyValueDatabaseCache();
$cache = new PhutilKeyValueCacheProfiler($cache);
$cache->setProfiler(PhutilServiceProfiler::getInstance());
$keys = array();
foreach ($pastes as $paste) {
$keys[] = $this->getSnippetCacheKey($paste);
}
$caches = $cache->getKeys($keys);
$need_raw = array();
$have_cache = array();
foreach ($pastes as $paste) {
$key = $this->getSnippetCacheKey($paste);
if (isset($caches[$key])) {
$snippet_data = phutil_json_decode($caches[$key]);
$snippet = new PhabricatorPasteSnippet(
phutil_safe_html($snippet_data['content']),
$snippet_data['type'],
$snippet_data['contentLineCount']);
$paste->attachSnippet($snippet);
$have_cache[$paste->getPHID()] = true;
} else {
$need_raw[$key] = $paste;
}
}
if (!$need_raw) {
return $pastes;
}
$write_data = array();
$have_raw = $this->loadRawContent($need_raw);
$have_raw = mpull($have_raw, null, 'getPHID');
foreach ($pastes as $key => $paste) {
$paste_phid = $paste->getPHID();
if (isset($have_cache[$paste_phid])) {
continue;
}
if (empty($have_raw[$paste_phid])) {
unset($pastes[$key]);
continue;
}
$snippet = $this->buildSnippet($paste);
$paste->attachSnippet($snippet);
$snippet_data = array(
'content' => (string)$snippet->getContent(),
'type' => (string)$snippet->getType(),
'contentLineCount' => $snippet->getContentLineCount(),
);
$write_data[$this->getSnippetCacheKey($paste)] = phutil_json_encode(
$snippet_data);
}
if ($write_data) {
$cache->setKeys($write_data);
}
return $pastes;
}
private function buildContent(PhabricatorPaste $paste) {
return $this->highlightSource(
$paste->getRawContent(),
$paste->getTitle(),
$paste->getLanguage());
}
private function buildSnippet(PhabricatorPaste $paste) {
$snippet_type = PhabricatorPasteSnippet::FULL;
$snippet = $paste->getRawContent();
$lines = phutil_split_lines($snippet);
$line_count = count($lines);
if (strlen($snippet) > 1024) {
$snippet_type = PhabricatorPasteSnippet::FIRST_BYTES;
$snippet = id(new PhutilUTF8StringTruncator())
->setMaximumBytes(1024)
->setTerminator('')
->truncateString($snippet);
}
if ($line_count > 5) {
$snippet_type = PhabricatorPasteSnippet::FIRST_LINES;
$snippet = implode('', array_slice($lines, 0, 5));
}
return new PhabricatorPasteSnippet(
$this->highlightSource(
$snippet,
$paste->getTitle(),
$paste->getLanguage()),
$snippet_type,
$line_count);
}
private function highlightSource($source, $title, $language) {
if (empty($language)) {
return PhabricatorSyntaxHighlighter::highlightWithFilename(
$title,
$source);
} else {
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
$language,
$source);
}
}
public function getQueryApplicationClass() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
}
diff --git a/src/applications/paste/query/PhabricatorPasteSearchEngine.php b/src/applications/paste/query/PhabricatorPasteSearchEngine.php
index e269088f60..88482b94cc 100644
--- a/src/applications/paste/query/PhabricatorPasteSearchEngine.php
+++ b/src/applications/paste/query/PhabricatorPasteSearchEngine.php
@@ -1,224 +1,224 @@
<?php
final class PhabricatorPasteSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Pastes');
}
public function getApplicationClassName() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
public function newQuery() {
return id(new PhabricatorPasteQuery())
->needSnippets(true);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['languages']) {
$query->withLanguages($map['languages']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedBefore($map['createdEnd']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setAliases(array('authors'))
->setKey('authorPHIDs')
->setConduitKey('authors')
->setLabel(pht('Authors'))
->setDescription(
pht('Search for pastes with specific authors.')),
id(new PhabricatorSearchStringListField())
->setKey('languages')
->setLabel(pht('Languages'))
->setDescription(
pht('Search for pastes highlighted in specific languages.')),
id(new PhabricatorSearchDateField())
->setKey('createdStart')
->setLabel(pht('Created After'))
->setDescription(
pht('Search for pastes created after a given time.')),
id(new PhabricatorSearchDateField())
->setKey('createdEnd')
->setLabel(pht('Created Before'))
->setDescription(
pht('Search for pastes created before a given time.')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setDescription(
pht('Search for archived or active pastes.'))
->setOptions(
id(new PhabricatorPaste())
->getStatusNameMap()),
);
}
protected function getDefaultFieldOrder() {
return array(
'...',
'createdStart',
'createdEnd',
);
}
protected function getURI($path) {
return '/paste/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Pastes'),
'all' => pht('All Pastes'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter(
'statuses',
array(
PhabricatorPaste::STATUS_ACTIVE,
));
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $pastes,
PhabricatorSavedQuery $query) {
return mpull($pastes, 'getAuthorPHID');
}
protected function renderResultList(
array $pastes,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($pastes, 'PhabricatorPaste');
$viewer = $this->requireViewer();
$lang_map = PhabricatorEnv::getEnvConfig('pygments.dropdown-choices');
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($pastes as $paste) {
$created = phabricator_date($paste->getDateCreated(), $viewer);
$author = $handles[$paste->getAuthorPHID()]->renderLink();
$snippet_type = $paste->getSnippet()->getType();
$lines = phutil_split_lines($paste->getSnippet()->getContent());
$preview = id(new PhabricatorSourceCodeView())
->setLines($lines)
->setTruncatedFirstBytes(
$snippet_type == PhabricatorPasteSnippet::FIRST_BYTES)
->setTruncatedFirstLines(
$snippet_type == PhabricatorPasteSnippet::FIRST_LINES)
->setURI(new PhutilURI($paste->getURI()));
$source_code = phutil_tag(
'div',
array(
'class' => 'phabricator-source-code-summary',
),
$preview);
$created = phabricator_datetime($paste->getDateCreated(), $viewer);
$line_count = $paste->getSnippet()->getContentLineCount();
$line_count = pht(
'%s Line(s)',
new PhutilNumber($line_count));
$title = nonempty($paste->getTitle(), pht('(An Untitled Masterwork)'));
$item = id(new PHUIObjectItemView())
->setObjectName('P'.$paste->getID())
->setHeader($title)
->setHref('/P'.$paste->getID())
->setObject($paste)
->addByline(pht('Author: %s', $author))
->addIcon('none', $created)
->addIcon('none', $line_count)
->appendChild($source_code);
if ($paste->isArchived()) {
$item->setDisabled(true);
}
$lang_name = $paste->getLanguage();
if ($lang_name) {
$lang_name = idx($lang_map, $lang_name, $lang_name);
$item->addIcon('none', $lang_name);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No pastes found.'));
return $result;
}
protected function getNewUserBody() {
$viewer = $this->requireViewer();
$create_button = id(new PhabricatorPasteEditEngine())
->setViewer($viewer)
->newNUXButton(pht('Create a Paste'));
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Store, share, and embed snippets of code.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/paste/typeahead/PasteLanguageSelectDatasource.php b/src/applications/paste/typeahead/PasteLanguageSelectDatasource.php
index 45c36db968..4bdf0b545c 100644
--- a/src/applications/paste/typeahead/PasteLanguageSelectDatasource.php
+++ b/src/applications/paste/typeahead/PasteLanguageSelectDatasource.php
@@ -1,42 +1,42 @@
<?php
final class PasteLanguageSelectDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Languages');
}
public function getPlaceholderText() {
return pht('Type a language name or leave blank to auto-detect...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPasteApplication';
+ return PhabricatorPasteApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$languages = PhabricatorEnv::getEnvConfig('pygments.dropdown-choices');
foreach ($languages as $value => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setPHID($value)
->setName($name);
$results[$value] = $result;
}
return $results;
}
}
diff --git a/src/applications/people/editor/PhabricatorUserEditEngine.php b/src/applications/people/editor/PhabricatorUserEditEngine.php
index 4b3a60a2fc..05738145f9 100644
--- a/src/applications/people/editor/PhabricatorUserEditEngine.php
+++ b/src/applications/people/editor/PhabricatorUserEditEngine.php
@@ -1,91 +1,91 @@
<?php
final class PhabricatorUserEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'people.user';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Users');
}
public function getSummaryHeader() {
return pht('Configure User Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms for users.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
protected function newEditableObject() {
return new PhabricatorUser();
}
protected function newObjectQuery() {
return id(new PhabricatorPeopleQuery());
}
protected function getObjectCreateTitleText($object) {
return pht('Create New User');
}
protected function getObjectEditTitleText($object) {
return pht('Edit User: %s', $object->getUsername());
}
protected function getObjectEditShortText($object) {
return $object->getMonogram();
}
protected function getObjectCreateShortText() {
return pht('Create User');
}
protected function getObjectName() {
return pht('User');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
// At least for now, forbid creating new users via EditEngine. This is
// primarily enforcing that "user.edit" can not create users via the API.
return PhabricatorPolicies::POLICY_NOONE;
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorBoolEditField())
->setKey('disabled')
->setOptions(pht('Active'), pht('Disabled'))
->setLabel(pht('Disabled'))
->setDescription(pht('Disable the user.'))
->setTransactionType(PhabricatorUserDisableTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Disable or enable the user.'))
->setConduitTypeDescription(pht('True to disable the user.'))
->setValue($object->getIsDisabled()),
id(new PhabricatorBoolEditField())
->setKey('approved')
->setOptions(pht('Approved'), pht('Unapproved'))
->setLabel(pht('Approved'))
->setDescription(pht('Approve the user.'))
->setTransactionType(PhabricatorUserApproveTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setConduitDescription(pht('Approve or reject the user.'))
->setConduitTypeDescription(pht('True to approve the user.'))
->setValue($object->getIsApproved()),
);
}
}
diff --git a/src/applications/people/editor/PhabricatorUserTransactionEditor.php b/src/applications/people/editor/PhabricatorUserTransactionEditor.php
index 929b2e224c..88c27d7ee8 100644
--- a/src/applications/people/editor/PhabricatorUserTransactionEditor.php
+++ b/src/applications/people/editor/PhabricatorUserTransactionEditor.php
@@ -1,28 +1,28 @@
<?php
final class PhabricatorUserTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Users');
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array();
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
}
diff --git a/src/applications/people/phid/PhabricatorPeopleExternalIdentifierPHIDType.php b/src/applications/people/phid/PhabricatorPeopleExternalIdentifierPHIDType.php
index acd9a24f56..2e2862892f 100644
--- a/src/applications/people/phid/PhabricatorPeopleExternalIdentifierPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleExternalIdentifierPHIDType.php
@@ -1,38 +1,38 @@
<?php
final class PhabricatorPeopleExternalIdentifierPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'XIDT';
public function getTypeName() {
return pht('External Account Identifier');
}
public function newObject() {
return new PhabricatorExternalAccountIdentifier();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorExternalAccountIdentifierQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$identifier = $objects[$phid];
}
}
}
diff --git a/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php b/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php
index 4be4cc5359..ebda57c423 100644
--- a/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorPeopleExternalPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'XUSR';
public function getTypeName() {
return pht('External Account');
}
public function newObject() {
return new PhabricatorExternalAccount();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorExternalAccountQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$account = $objects[$phid];
$display_name = $account->getDisplayName();
$handle->setName($display_name);
}
}
}
diff --git a/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php
index e0f0478033..206b27d77e 100644
--- a/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorPeopleUserEmailPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'EADR';
public function getTypeName() {
return pht('User Email');
}
public function newObject() {
return new PhabricatorUserEmail();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPeopleUserEmailQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$email = $objects[$phid];
$handle->setName($email->getAddress());
}
return null;
}
}
diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
index 7867f098f1..65139814b7 100644
--- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
+++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php
@@ -1,121 +1,121 @@
<?php
final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'USER';
public function getTypeName() {
return pht('User');
}
public function getTypeIcon() {
return 'fa-user bluegrey';
}
public function newObject() {
return new PhabricatorUser();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPeopleQuery())
->withPHIDs($phids)
->needProfile(true)
->needProfileImage(true)
->needAvailability(true);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$user = $objects[$phid];
$realname = $user->getRealName();
$username = $user->getUsername();
$handle
->setName($username)
->setURI('/p/'.$username.'/')
->setFullName($user->getFullName())
->setImageURI($user->getProfileImageURI())
->setMailStampName('@'.$username);
if ($user->getIsMailingList()) {
$handle->setIcon('fa-envelope-o');
$handle->setSubtitle(pht('Mailing List'));
} else {
$profile = $user->getUserProfile();
$icon_key = $profile->getIcon();
$icon_icon = PhabricatorPeopleIconSet::getIconIcon($icon_key);
$subtitle = $profile->getDisplayTitle();
$handle
->setIcon($icon_icon)
->setSubtitle($subtitle)
->setTokenIcon('fa-user');
}
$availability = null;
if ($user->getIsDisabled()) {
$availability = PhabricatorObjectHandle::AVAILABILITY_DISABLED;
} else if (!$user->isResponsive()) {
$availability = PhabricatorObjectHandle::AVAILABILITY_NOEMAIL;
} else {
$until = $user->getAwayUntil();
if ($until) {
$away = PhabricatorCalendarEventInvitee::AVAILABILITY_AWAY;
if ($user->getDisplayAvailability() == $away) {
$availability = PhabricatorObjectHandle::AVAILABILITY_NONE;
} else {
$availability = PhabricatorObjectHandle::AVAILABILITY_PARTIAL;
}
}
}
if ($availability) {
$handle->setAvailability($availability);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^@.+/', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = substr($name, 1);
$id = phutil_utf8_strtolower($id);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorPeopleQuery())
->setViewer($query->getViewer())
->withUsernames(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
$user_key = $object->getUsername();
$user_key = phutil_utf8_strtolower($user_key);
foreach (idx($id_map, $user_key, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleLogQuery.php b/src/applications/people/query/PhabricatorPeopleLogQuery.php
index e87fb33660..d439894e5c 100644
--- a/src/applications/people/query/PhabricatorPeopleLogQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleLogQuery.php
@@ -1,135 +1,135 @@
<?php
final class PhabricatorPeopleLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $actorPHIDs;
private $userPHIDs;
private $relatedPHIDs;
private $sessionKeys;
private $actions;
private $remoteAddressPrefix;
private $dateCreatedMin;
private $dateCreatedMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withActorPHIDs(array $actor_phids) {
$this->actorPHIDs = $actor_phids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withRelatedPHIDs(array $related_phids) {
$this->relatedPHIDs = $related_phids;
return $this;
}
public function withSessionKeys(array $session_keys) {
$this->sessionKeys = $session_keys;
return $this;
}
public function withActions(array $actions) {
$this->actions = $actions;
return $this;
}
public function withRemoteAddressPrefix($remote_address_prefix) {
$this->remoteAddressPrefix = $remote_address_prefix;
return $this;
}
public function withDateCreatedBetween($min, $max) {
$this->dateCreatedMin = $min;
$this->dateCreatedMax = $max;
return $this;
}
public function newResultObject() {
return new PhabricatorUserLog();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->actorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'actorPHID IN (%Ls)',
$this->actorPHIDs);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->relatedPHIDs !== null) {
$where[] = qsprintf(
$conn,
'(actorPHID IN (%Ls) OR userPHID IN (%Ls))',
$this->relatedPHIDs,
$this->relatedPHIDs);
}
if ($this->sessionKeys !== null) {
$where[] = qsprintf(
$conn,
'session IN (%Ls)',
$this->sessionKeys);
}
if ($this->actions !== null) {
$where[] = qsprintf(
$conn,
'action IN (%Ls)',
$this->actions);
}
if ($this->remoteAddressPrefix !== null) {
$where[] = qsprintf(
$conn,
'remoteAddr LIKE %>',
$this->remoteAddressPrefix);
}
if ($this->dateCreatedMin !== null) {
$where[] = qsprintf(
$conn,
'dateCreated >= %d',
$this->dateCreatedMin);
}
if ($this->dateCreatedMax !== null) {
$where[] = qsprintf(
$conn,
'dateCreated <= %d',
$this->dateCreatedMax);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleLogSearchEngine.php b/src/applications/people/query/PhabricatorPeopleLogSearchEngine.php
index 7e7fca1cd4..fc1819debc 100644
--- a/src/applications/people/query/PhabricatorPeopleLogSearchEngine.php
+++ b/src/applications/people/query/PhabricatorPeopleLogSearchEngine.php
@@ -1,245 +1,245 @@
<?php
final class PhabricatorPeopleLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Account Activity');
}
public function getApplicationClassName() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getPageSize(PhabricatorSavedQuery $saved) {
return 500;
}
public function newQuery() {
$query = new PhabricatorPeopleLogQuery();
// NOTE: If the viewer isn't an administrator, always restrict the query to
// related records. This echoes the policy logic of these logs. This is
// mostly a performance optimization, to prevent us from having to pull
// large numbers of logs that the user will not be able to see and filter
// them in-process.
$viewer = $this->requireViewer();
if (!$viewer->getIsAdmin()) {
$query->withRelatedPHIDs(array($viewer->getPHID()));
}
return $query;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['userPHIDs']) {
$query->withUserPHIDs($map['userPHIDs']);
}
if ($map['actorPHIDs']) {
$query->withActorPHIDs($map['actorPHIDs']);
}
if ($map['actions']) {
$query->withActions($map['actions']);
}
if (strlen($map['ip'])) {
$query->withRemoteAddressPrefix($map['ip']);
}
if ($map['sessions']) {
$query->withSessionKeys($map['sessions']);
}
if ($map['createdStart'] || $map['createdEnd']) {
$query->withDateCreatedBetween(
$map['createdStart'],
$map['createdEnd']);
}
return $query;
}
protected function buildCustomSearchFields() {
$types = PhabricatorUserLogType::getAllLogTypes();
$types = mpull($types, 'getLogTypeName', 'getLogTypeKey');
return array(
id(new PhabricatorUsersSearchField())
->setKey('userPHIDs')
->setAliases(array('users', 'user', 'userPHID'))
->setLabel(pht('Users'))
->setDescription(pht('Search for activity affecting specific users.')),
id(new PhabricatorUsersSearchField())
->setKey('actorPHIDs')
->setAliases(array('actors', 'actor', 'actorPHID'))
->setLabel(pht('Actors'))
->setDescription(pht('Search for activity by specific users.')),
id(new PhabricatorSearchDatasourceField())
->setKey('actions')
->setLabel(pht('Actions'))
->setDescription(pht('Search for particular types of activity.'))
->setDatasource(new PhabricatorUserLogTypeDatasource()),
id(new PhabricatorSearchTextField())
->setKey('ip')
->setLabel(pht('Filter IP'))
->setDescription(pht('Search for actions by remote address.')),
id(new PhabricatorSearchStringListField())
->setKey('sessions')
->setLabel(pht('Sessions'))
->setDescription(pht('Search for activity in particular sessions.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function getURI($path) {
return '/people/logs/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($logs, 'PhabricatorUserLog');
$viewer = $this->requireViewer();
$table = id(new PhabricatorUserLogView())
->setUser($viewer)
->setLogs($logs);
if ($viewer->getIsAdmin()) {
$table->setSearchBaseURI($this->getApplicationURI('logs/'));
}
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
protected function newExportFields() {
$viewer = $this->requireViewer();
$fields = array(
$fields[] = id(new PhabricatorPHIDExportField())
->setKey('actorPHID')
->setLabel(pht('Actor PHID')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('actor')
->setLabel(pht('Actor')),
$fields[] = id(new PhabricatorPHIDExportField())
->setKey('userPHID')
->setLabel(pht('User PHID')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('user')
->setLabel(pht('User')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('action')
->setLabel(pht('Action')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('actionName')
->setLabel(pht('Action Name')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('session')
->setLabel(pht('Session')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('old')
->setLabel(pht('Old Value')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('new')
->setLabel(pht('New Value')),
);
if ($viewer->getIsAdmin()) {
$fields[] = id(new PhabricatorStringExportField())
->setKey('remoteAddress')
->setLabel(pht('Remote Address'));
}
return $fields;
}
protected function newExportData(array $logs) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($logs as $log) {
$phids[] = $log->getUserPHID();
$phids[] = $log->getActorPHID();
}
$handles = $viewer->loadHandles($phids);
$types = PhabricatorUserLogType::getAllLogTypes();
$types = mpull($types, 'getLogTypeName', 'getLogTypeKey');
$export = array();
foreach ($logs as $log) {
$user_phid = $log->getUserPHID();
if ($user_phid) {
$user_name = $handles[$user_phid]->getName();
} else {
$user_name = null;
}
$actor_phid = $log->getActorPHID();
if ($actor_phid) {
$actor_name = $handles[$actor_phid]->getName();
} else {
$actor_name = null;
}
$action = $log->getAction();
$action_name = idx($types, $action, pht('Unknown ("%s")', $action));
$map = array(
'actorPHID' => $actor_phid,
'actor' => $actor_name,
'userPHID' => $user_phid,
'user' => $user_name,
'action' => $action,
'actionName' => $action_name,
'session' => substr($log->getSession(), 0, 6),
'old' => $log->getOldValue(),
'new' => $log->getNewValue(),
);
if ($viewer->getIsAdmin()) {
$map['remoteAddress'] = $log->getRemoteAddr();
}
$export[] = $map;
}
return $export;
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
index b74b936ba8..acbeb3b34f 100644
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -1,630 +1,630 @@
<?php
final class PhabricatorPeopleQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $usernames;
private $realnames;
private $emails;
private $phids;
private $ids;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $isAdmin;
private $isSystemAgent;
private $isMailingList;
private $isDisabled;
private $isApproved;
private $nameLike;
private $nameTokens;
private $namePrefixes;
private $isEnrolledInMultiFactor;
private $needPrimaryEmail;
private $needProfile;
private $needProfileImage;
private $needAvailability;
private $needBadgeAwards;
private $cacheKeys = array();
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withEmails(array $emails) {
$this->emails = $emails;
return $this;
}
public function withRealnames(array $realnames) {
$this->realnames = $realnames;
return $this;
}
public function withUsernames(array $usernames) {
$this->usernames = $usernames;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withIsAdmin($admin) {
$this->isAdmin = $admin;
return $this;
}
public function withIsSystemAgent($system_agent) {
$this->isSystemAgent = $system_agent;
return $this;
}
public function withIsMailingList($mailing_list) {
$this->isMailingList = $mailing_list;
return $this;
}
public function withIsDisabled($disabled) {
$this->isDisabled = $disabled;
return $this;
}
public function withIsApproved($approved) {
$this->isApproved = $approved;
return $this;
}
public function withNameLike($like) {
$this->nameLike = $like;
return $this;
}
public function withNameTokens(array $tokens) {
$this->nameTokens = array_values($tokens);
return $this;
}
public function withNamePrefixes(array $prefixes) {
$this->namePrefixes = $prefixes;
return $this;
}
public function withIsEnrolledInMultiFactor($enrolled) {
$this->isEnrolledInMultiFactor = $enrolled;
return $this;
}
public function needPrimaryEmail($need) {
$this->needPrimaryEmail = $need;
return $this;
}
public function needProfile($need) {
$this->needProfile = $need;
return $this;
}
public function needProfileImage($need) {
$cache_key = PhabricatorUserProfileImageCacheType::KEY_URI;
if ($need) {
$this->cacheKeys[$cache_key] = true;
} else {
unset($this->cacheKeys[$cache_key]);
}
return $this;
}
public function needAvailability($need) {
$this->needAvailability = $need;
return $this;
}
public function needUserSettings($need) {
$cache_key = PhabricatorUserPreferencesCacheType::KEY_PREFERENCES;
if ($need) {
$this->cacheKeys[$cache_key] = true;
} else {
unset($this->cacheKeys[$cache_key]);
}
return $this;
}
public function needBadgeAwards($need) {
$cache_key = PhabricatorUserBadgesCacheType::KEY_BADGES;
if ($need) {
$this->cacheKeys[$cache_key] = true;
} else {
unset($this->cacheKeys[$cache_key]);
}
return $this;
}
public function newResultObject() {
return new PhabricatorUser();
}
protected function didFilterPage(array $users) {
if ($this->needProfile) {
$user_list = mpull($users, null, 'getPHID');
$profiles = new PhabricatorUserProfile();
$profiles = $profiles->loadAllWhere(
'userPHID IN (%Ls)',
array_keys($user_list));
$profiles = mpull($profiles, null, 'getUserPHID');
foreach ($user_list as $user_phid => $user) {
$profile = idx($profiles, $user_phid);
if (!$profile) {
$profile = PhabricatorUserProfile::initializeNewProfile($user);
}
$user->attachUserProfile($profile);
}
}
if ($this->needAvailability) {
$rebuild = array();
foreach ($users as $user) {
$cache = $user->getAvailabilityCache();
if ($cache !== null) {
$user->attachAvailability($cache);
} else {
$rebuild[] = $user;
}
}
if ($rebuild) {
$this->rebuildAvailabilityCache($rebuild);
}
}
$this->fillUserCaches($users);
return $users;
}
protected function shouldGroupQueryResultRows() {
if ($this->nameTokens) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->emails) {
$email_table = new PhabricatorUserEmail();
$joins[] = qsprintf(
$conn,
'JOIN %T email ON email.userPHID = user.PHID',
$email_table->getTableName());
}
if ($this->nameTokens) {
foreach ($this->nameTokens as $key => $token) {
$token_table = 'token_'.$key;
$joins[] = qsprintf(
$conn,
'JOIN %T %T ON %T.userID = user.id AND %T.token LIKE %>',
PhabricatorUser::NAMETOKEN_TABLE,
$token_table,
$token_table,
$token_table,
$token);
}
}
return $joins;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->usernames !== null) {
$where[] = qsprintf(
$conn,
'user.userName IN (%Ls)',
$this->usernames);
}
if ($this->namePrefixes) {
$parts = array();
foreach ($this->namePrefixes as $name_prefix) {
$parts[] = qsprintf(
$conn,
'user.username LIKE %>',
$name_prefix);
}
$where[] = qsprintf($conn, '%LO', $parts);
}
if ($this->emails !== null) {
$where[] = qsprintf(
$conn,
'email.address IN (%Ls)',
$this->emails);
}
if ($this->realnames !== null) {
$where[] = qsprintf(
$conn,
'user.realName IN (%Ls)',
$this->realnames);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'user.phid IN (%Ls)',
$this->phids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'user.id IN (%Ld)',
$this->ids);
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn,
'user.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn,
'user.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->isAdmin !== null) {
$where[] = qsprintf(
$conn,
'user.isAdmin = %d',
(int)$this->isAdmin);
}
if ($this->isDisabled !== null) {
$where[] = qsprintf(
$conn,
'user.isDisabled = %d',
(int)$this->isDisabled);
}
if ($this->isApproved !== null) {
$where[] = qsprintf(
$conn,
'user.isApproved = %d',
(int)$this->isApproved);
}
if ($this->isSystemAgent !== null) {
$where[] = qsprintf(
$conn,
'user.isSystemAgent = %d',
(int)$this->isSystemAgent);
}
if ($this->isMailingList !== null) {
$where[] = qsprintf(
$conn,
'user.isMailingList = %d',
(int)$this->isMailingList);
}
if ($this->nameLike !== null) {
$where[] = qsprintf(
$conn,
'user.username LIKE %~ OR user.realname LIKE %~',
$this->nameLike,
$this->nameLike);
}
if ($this->isEnrolledInMultiFactor !== null) {
$where[] = qsprintf(
$conn,
'user.isEnrolledInMultiFactor = %d',
(int)$this->isEnrolledInMultiFactor);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'user';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'username' => array(
'table' => 'user',
'column' => 'username',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'username' => $object->getUsername(),
);
}
private function rebuildAvailabilityCache(array $rebuild) {
$rebuild = mpull($rebuild, null, 'getPHID');
// Limit the window we look at because far-future events are largely
// irrelevant and this makes the cache cheaper to build and allows it to
// self-heal over time.
$min_range = PhabricatorTime::getNow();
$max_range = $min_range + phutil_units('72 hours in seconds');
// NOTE: We don't need to generate ghosts here, because we only care if
// the user is attending, and you can't attend a ghost event: RSVP'ing
// to it creates a real event.
$events = id(new PhabricatorCalendarEventQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withInvitedPHIDs(array_keys($rebuild))
->withIsCancelled(false)
->withDateRange($min_range, $max_range)
->execute();
// Group all the events by invited user. Only examine events that users
// are actually attending.
$map = array();
$invitee_map = array();
foreach ($events as $event) {
foreach ($event->getInvitees() as $invitee) {
if (!$invitee->isAttending()) {
continue;
}
// If the user is set to "Available" for this event, don't consider it
// when computing their away status.
if (!$invitee->getDisplayAvailability($event)) {
continue;
}
$invitee_phid = $invitee->getInviteePHID();
if (!isset($rebuild[$invitee_phid])) {
continue;
}
$map[$invitee_phid][] = $event;
$event_phid = $event->getPHID();
$invitee_map[$invitee_phid][$event_phid] = $invitee;
}
}
// We need to load these users' timezone settings to figure out their
// availability if they're attending all-day events.
$this->needUserSettings(true);
$this->fillUserCaches($rebuild);
foreach ($rebuild as $phid => $user) {
$events = idx($map, $phid, array());
// We loaded events with the omnipotent user, but want to shift them
// into the user's timezone before building the cache because they will
// be unavailable during their own local day.
foreach ($events as $event) {
$event->applyViewerTimezone($user);
}
$cursor = $min_range;
$next_event = null;
if ($events) {
// Find the next time when the user has no meetings. If we move forward
// because of an event, we check again for events after that one ends.
while (true) {
foreach ($events as $event) {
$from = $event->getStartDateTimeEpochForCache();
$to = $event->getEndDateTimeEpochForCache();
if (($from <= $cursor) && ($to > $cursor)) {
$cursor = $to;
if (!$next_event) {
$next_event = $event;
}
continue 2;
}
}
break;
}
}
if ($cursor > $min_range) {
$invitee = $invitee_map[$phid][$next_event->getPHID()];
$availability_type = $invitee->getDisplayAvailability($next_event);
$availability = array(
'until' => $cursor,
'eventPHID' => $next_event->getPHID(),
'availability' => $availability_type,
);
// We only cache this availability until the end of the current event,
// since the event PHID (and possibly the availability type) are only
// valid for that long.
// NOTE: This doesn't handle overlapping events with the greatest
// possible care. In theory, if you're attending multiple events
// simultaneously we should accommodate that. However, it's complex
// to compute, rare, and probably not confusing most of the time.
$availability_ttl = $next_event->getEndDateTimeEpochForCache();
} else {
$availability = array(
'until' => null,
'eventPHID' => null,
'availability' => null,
);
// Cache that the user is available until the next event they are
// invited to starts.
$availability_ttl = $max_range;
foreach ($events as $event) {
$from = $event->getStartDateTimeEpochForCache();
if ($from > $cursor) {
$availability_ttl = min($from, $availability_ttl);
}
}
}
// Never TTL the cache to longer than the maximum range we examined.
$availability_ttl = min($availability_ttl, $max_range);
$user->writeAvailabilityCache($availability, $availability_ttl);
$user->attachAvailability($availability);
}
}
private function fillUserCaches(array $users) {
if (!$this->cacheKeys) {
return;
}
$user_map = mpull($users, null, 'getPHID');
$keys = array_keys($this->cacheKeys);
$hashes = array();
foreach ($keys as $key) {
$hashes[] = PhabricatorHash::digestForIndex($key);
}
$types = PhabricatorUserCacheType::getAllCacheTypes();
// First, pull any available caches. If we wanted to be particularly clever
// we could do this with JOINs in the main query.
$cache_table = new PhabricatorUserCache();
$cache_conn = $cache_table->establishConnection('r');
$cache_data = queryfx_all(
$cache_conn,
'SELECT cacheKey, userPHID, cacheData, cacheType FROM %T
WHERE cacheIndex IN (%Ls) AND userPHID IN (%Ls)',
$cache_table->getTableName(),
$hashes,
array_keys($user_map));
$skip_validation = array();
// After we read caches from the database, discard any which have data that
// invalid or out of date. This allows cache types to implement TTLs or
// versions instead of or in addition to explicit cache clears.
foreach ($cache_data as $row_key => $row) {
$cache_type = $row['cacheType'];
if (isset($skip_validation[$cache_type])) {
continue;
}
if (empty($types[$cache_type])) {
unset($cache_data[$row_key]);
continue;
}
$type = $types[$cache_type];
if (!$type->shouldValidateRawCacheData()) {
$skip_validation[$cache_type] = true;
continue;
}
$user = $user_map[$row['userPHID']];
$raw_data = $row['cacheData'];
if (!$type->isRawCacheDataValid($user, $row['cacheKey'], $raw_data)) {
unset($cache_data[$row_key]);
continue;
}
}
$need = array();
$cache_data = igroup($cache_data, 'userPHID');
foreach ($user_map as $user_phid => $user) {
$raw_rows = idx($cache_data, $user_phid, array());
$raw_data = ipull($raw_rows, 'cacheData', 'cacheKey');
foreach ($keys as $key) {
if (isset($raw_data[$key]) || array_key_exists($key, $raw_data)) {
continue;
}
$need[$key][$user_phid] = $user;
}
$user->attachRawCacheData($raw_data);
}
// If we missed any cache values, bulk-construct them now. This is
// usually much cheaper than generating them on-demand for each user
// record.
if (!$need) {
return;
}
$writes = array();
foreach ($need as $cache_key => $need_users) {
$type = PhabricatorUserCacheType::getCacheTypeForKey($cache_key);
if (!$type) {
continue;
}
$data = $type->newValueForUsers($cache_key, $need_users);
foreach ($data as $user_phid => $raw_value) {
$data[$user_phid] = $raw_value;
$writes[] = array(
'userPHID' => $user_phid,
'key' => $cache_key,
'type' => $type,
'value' => $raw_value,
);
}
foreach ($need_users as $user_phid => $user) {
if (isset($data[$user_phid]) || array_key_exists($user_phid, $data)) {
$user->attachRawCacheData(
array(
$cache_key => $data[$user_phid],
));
}
}
}
PhabricatorUserCache::writeCaches($writes);
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleSearchEngine.php b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
index bdeab953ec..1e0c0052c1 100644
--- a/src/applications/people/query/PhabricatorPeopleSearchEngine.php
+++ b/src/applications/people/query/PhabricatorPeopleSearchEngine.php
@@ -1,352 +1,352 @@
<?php
final class PhabricatorPeopleSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Users');
}
public function getApplicationClassName() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function newQuery() {
return id(new PhabricatorPeopleQuery())
->needPrimaryEmail(true)
->needProfileImage(true);
}
protected function buildCustomSearchFields() {
$fields = array(
id(new PhabricatorSearchStringListField())
->setLabel(pht('Usernames'))
->setKey('usernames')
->setAliases(array('username'))
->setDescription(pht('Find users by exact username.')),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('nameLike')
->setDescription(
pht('Find users whose usernames contain a substring.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Administrators'))
->setKey('isAdmin')
->setOptions(
pht('(Show All)'),
pht('Show Only Administrators'),
pht('Hide Administrators'))
->setDescription(
pht(
'Pass true to find only administrators, or false to omit '.
'administrators.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Disabled'))
->setKey('isDisabled')
->setOptions(
pht('(Show All)'),
pht('Show Only Disabled Users'),
pht('Hide Disabled Users'))
->setDescription(
pht(
'Pass true to find only disabled users, or false to omit '.
'disabled users.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Bots'))
->setKey('isBot')
->setAliases(array('isSystemAgent'))
->setOptions(
pht('(Show All)'),
pht('Show Only Bots'),
pht('Hide Bots'))
->setDescription(
pht(
'Pass true to find only bots, or false to omit bots.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Mailing Lists'))
->setKey('isMailingList')
->setOptions(
pht('(Show All)'),
pht('Show Only Mailing Lists'),
pht('Hide Mailing Lists'))
->setDescription(
pht(
'Pass true to find only mailing lists, or false to omit '.
'mailing lists.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Needs Approval'))
->setKey('needsApproval')
->setOptions(
pht('(Show All)'),
pht('Show Only Unapproved Users'),
pht('Hide Unapproved Users'))
->setDescription(
pht(
'Pass true to find only users awaiting administrative approval, '.
'or false to omit these users.')),
);
$viewer = $this->requireViewer();
if ($viewer->getIsAdmin()) {
$fields[] = id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Has MFA'))
->setKey('mfa')
->setOptions(
pht('(Show All)'),
pht('Show Only Users With MFA'),
pht('Hide Users With MFA'))
->setDescription(
pht(
'Pass true to find only users who are enrolled in MFA, or false '.
'to omit these users.'));
}
$fields[] = id(new PhabricatorSearchDateField())
->setKey('createdStart')
->setLabel(pht('Joined After'))
->setDescription(
pht('Find user accounts created after a given time.'));
$fields[] = id(new PhabricatorSearchDateField())
->setKey('createdEnd')
->setLabel(pht('Joined Before'))
->setDescription(
pht('Find user accounts created before a given time.'));
return $fields;
}
protected function getDefaultFieldOrder() {
return array(
'...',
'createdStart',
'createdEnd',
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$viewer = $this->requireViewer();
// If the viewer can't browse the user directory, restrict the query to
// just the user's own profile. This is a little bit silly, but serves to
// restrict users from creating a dashboard panel which essentially just
// contains a user directory anyway.
$can_browse = PhabricatorPolicyFilter::hasCapability(
$viewer,
$this->getApplication(),
PeopleBrowseUserDirectoryCapability::CAPABILITY);
if (!$can_browse) {
$query->withPHIDs(array($viewer->getPHID()));
}
if ($map['usernames']) {
$query->withUsernames($map['usernames']);
}
if ($map['nameLike']) {
$query->withNameLike($map['nameLike']);
}
if ($map['isAdmin'] !== null) {
$query->withIsAdmin($map['isAdmin']);
}
if ($map['isDisabled'] !== null) {
$query->withIsDisabled($map['isDisabled']);
}
if ($map['isMailingList'] !== null) {
$query->withIsMailingList($map['isMailingList']);
}
if ($map['isBot'] !== null) {
$query->withIsSystemAgent($map['isBot']);
}
if ($map['needsApproval'] !== null) {
$query->withIsApproved(!$map['needsApproval']);
}
if (idx($map, 'mfa') !== null) {
$viewer = $this->requireViewer();
if (!$viewer->getIsAdmin()) {
throw new PhabricatorSearchConstraintException(
pht(
'The "Has MFA" query constraint may only be used by '.
'administrators, to prevent attackers from using it to target '.
'weak accounts.'));
}
$query->withIsEnrolledInMultiFactor($map['mfa']);
}
if ($map['createdStart']) {
$query->withDateCreatedAfter($map['createdStart']);
}
if ($map['createdEnd']) {
$query->withDateCreatedBefore($map['createdEnd']);
}
return $query;
}
protected function getURI($path) {
return '/people/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active'),
'admin' => pht('Administrators'),
'all' => pht('All'),
);
$viewer = $this->requireViewer();
if ($viewer->getIsAdmin()) {
$names['approval'] = pht('Approval Queue');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query
->setParameter('isDisabled', false);
case 'admin':
return $query
->setParameter('isAdmin', true);
case 'approval':
return $query
->setParameter('needsApproval', true)
->setParameter('isDisabled', false);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $users,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($users, 'PhabricatorUser');
$request = $this->getRequest();
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$is_approval = ($query->getQueryKey() == 'approval');
foreach ($users as $user) {
$primary_email = $user->loadPrimaryEmail();
if ($primary_email && $primary_email->getIsVerified()) {
$email = pht('Verified');
} else {
$email = pht('Unverified');
}
$item = new PHUIObjectItemView();
$item->setHeader($user->getFullName())
->setHref('/p/'.$user->getUsername().'/')
->addAttribute(phabricator_datetime($user->getDateCreated(), $viewer))
->addAttribute($email)
->setImageURI($user->getProfileImageURI());
if ($is_approval && $primary_email) {
$item->addAttribute($primary_email->getAddress());
}
if ($user->getIsDisabled()) {
$item->addIcon('fa-ban', pht('Disabled'));
$item->setDisabled(true);
}
if (!$is_approval) {
if (!$user->getIsApproved()) {
$item->addIcon('fa-clock-o', pht('Needs Approval'));
}
}
if ($user->getIsAdmin()) {
$item->addIcon('fa-star', pht('Admin'));
}
if ($user->getIsSystemAgent()) {
$item->addIcon('fa-desktop', pht('Bot'));
}
if ($user->getIsMailingList()) {
$item->addIcon('fa-envelope-o', pht('Mailing List'));
}
if ($viewer->getIsAdmin()) {
if ($user->getIsEnrolledInMultiFactor()) {
$item->addIcon('fa-lock', pht('Has MFA'));
}
}
if ($viewer->getIsAdmin()) {
$user_id = $user->getID();
if ($is_approval) {
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-ban')
->setName(pht('Disable'))
->setWorkflow(true)
->setHref($this->getApplicationURI('disapprove/'.$user_id.'/')));
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-thumbs-o-up')
->setName(pht('Approve'))
->setWorkflow(true)
->setHref($this->getApplicationURI('approve/'.$user_id.'/')));
}
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No accounts found.'));
return $result;
}
protected function newExportFields() {
return array(
id(new PhabricatorStringExportField())
->setKey('username')
->setLabel(pht('Username')),
id(new PhabricatorStringExportField())
->setKey('realName')
->setLabel(pht('Real Name')),
);
}
protected function newExportData(array $users) {
$viewer = $this->requireViewer();
$export = array();
foreach ($users as $user) {
$export[] = array(
'username' => $user->getUsername(),
'realName' => $user->getRealName(),
);
}
return $export;
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
index ead44a56dc..178a3b9460 100644
--- a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php
@@ -1,77 +1,77 @@
<?php
final class PhabricatorPeopleUserEmailQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorUserEmail();
}
protected function getPrimaryTableAlias() {
return 'email';
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'email.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'email.phid IN (%Ls)',
$this->phids);
}
return $where;
}
protected function willLoadPage(array $page) {
$user_phids = mpull($page, 'getUserPHID');
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($user_phids)
->execute();
$users = mpull($users, null, 'getPHID');
foreach ($page as $key => $address) {
$user = idx($users, $address->getUserPHID());
if (!$user) {
unset($page[$key]);
$this->didRejectResult($address);
continue;
}
$address->attachUser($user);
}
return $page;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
}
diff --git a/src/applications/people/typeahead/PhabricatorPeopleAnyOwnerDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleAnyOwnerDatasource.php
index 2a2a451a49..5a8e70f1b8 100644
--- a/src/applications/people/typeahead/PhabricatorPeopleAnyOwnerDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorPeopleAnyOwnerDatasource.php
@@ -1,69 +1,69 @@
<?php
final class PhabricatorPeopleAnyOwnerDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'anyone()';
public function getBrowseTitle() {
return pht('Browse Any Owner');
}
public function getPlaceholderText() {
return pht('Type "anyone()"...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'anyone' => array(
'name' => pht('Anyone'),
'summary' => pht('Find results which are assigned to anyone.'),
'description' => pht(
'This function includes results which have any owner. It excludes '.
'unassigned or unowned results.'),
),
);
}
public function loadResults() {
$results = array(
$this->buildAnyoneResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = self::FUNCTION_TOKEN;
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildAnyoneResult());
}
return $results;
}
private function buildAnyoneResult() {
$name = pht('Any Owner');
return $this->newFunctionResult()
->setName($name.' anyone')
->setDisplayName($name)
->setIcon('fa-certificate')
->setPHID(self::FUNCTION_TOKEN)
->setUnique(true)
->addAttribute(pht('Select results with any owner.'));
}
}
diff --git a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
index d4a5ad96c7..c06ba5b458 100644
--- a/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorPeopleDatasource.php
@@ -1,114 +1,114 @@
<?php
final class PhabricatorPeopleDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Users');
}
public function getPlaceholderText() {
return pht('Type a username...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$query = id(new PhabricatorPeopleQuery())
->setOrderVector(array('username'))
->needAvailability(true);
if ($this->getPhase() == self::PHASE_PREFIX) {
$prefix = $this->getPrefixQuery();
$query->withNamePrefixes(array($prefix));
} else {
$tokens = $this->getTokens();
if ($tokens) {
$query->withNameTokens($tokens);
}
}
$users = $this->executeQuery($query);
$is_browse = $this->getIsBrowse();
if ($is_browse && $users) {
$phids = mpull($users, 'getPHID');
$handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($phids)
->execute();
}
$results = array();
foreach ($users as $user) {
$phid = $user->getPHID();
$closed = null;
if ($user->getIsDisabled()) {
$closed = pht('Disabled');
} else if ($user->getIsSystemAgent()) {
$closed = pht('Bot');
} else if ($user->getIsMailingList()) {
$closed = pht('Mailing List');
}
$username = $user->getUsername();
$result = id(new PhabricatorTypeaheadResult())
->setName($user->getFullName())
->setURI('/p/'.$username.'/')
->setPHID($phid)
->setPriorityString($username)
->setPriorityType('user')
->setAutocomplete('@'.$username)
->setClosed($closed);
if ($user->getIsMailingList()) {
$result->setIcon('fa-envelope-o');
}
if ($is_browse) {
$handle = $handles[$phid];
$result
->setIcon($handle->getIcon())
->setImageURI($handle->getImageURI())
->addAttribute($handle->getSubtitle());
if ($user->getIsAdmin()) {
$result->addAttribute(
array(
id(new PHUIIconView())->setIcon('fa-star'),
' ',
pht('Administrator'),
));
}
if ($user->getIsAdmin()) {
$display_type = pht('Administrator');
} else {
$display_type = pht('User');
}
$result->setDisplayType($display_type);
}
$until = $user->getAwayUntil();
if ($until) {
$availability = $user->getDisplayAvailability();
$color = PhabricatorCalendarEventInvitee::getAvailabilityColor(
$availability);
$result->setAvailabilityColor($color);
}
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php b/src/applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php
index fb3a6226d9..cd3f2939b9 100644
--- a/src/applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php
@@ -1,76 +1,76 @@
<?php
final class PhabricatorPeopleNoOwnerDatasource
extends PhabricatorTypeaheadDatasource {
const FUNCTION_TOKEN = 'none()';
public function getBrowseTitle() {
return pht('Browse No Owner');
}
public function getPlaceholderText() {
return pht('Type "none"...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'none' => array(
'name' => pht('No Owner'),
'summary' => pht('Find results which are not assigned.'),
'description' => pht(
"This function includes results which have no owner. Use a query ".
"like this to find unassigned results:\n\n%s\n\n".
"If you combine this function with other functions, the query will ".
"return results which match the other selectors //or// have no ".
"owner. For example, this query will find results which are owned ".
"by `alincoln`, and will also find results which have no owner:".
"\n\n%s",
'> none()',
'> alincoln, none()'),
),
);
}
public function loadResults() {
$results = array(
$this->buildNoOwnerResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = self::FUNCTION_TOKEN;
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildNoOwnerResult());
}
return $results;
}
private function buildNoOwnerResult() {
$name = pht('No Owner');
return $this->newFunctionResult()
->setName($name.' none')
->setDisplayName($name)
->setIcon('fa-ban')
->setPHID('none()')
->setUnique(true)
->addAttribute(pht('Select results with no owner.'));
}
}
diff --git a/src/applications/people/typeahead/PhabricatorUserLogTypeDatasource.php b/src/applications/people/typeahead/PhabricatorUserLogTypeDatasource.php
index 39241a020c..26ccdfe2ea 100644
--- a/src/applications/people/typeahead/PhabricatorUserLogTypeDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorUserLogTypeDatasource.php
@@ -1,43 +1,43 @@
<?php
final class PhabricatorUserLogTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Log Types');
}
public function getPlaceholderText() {
return pht('Type a log type name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$type_map = PhabricatorUserLogType::getAllLogTypes();
foreach ($type_map as $type_key => $type) {
$result = id(new PhabricatorTypeaheadResult())
->setPHID($type_key)
->setName($type->getLogTypeName());
$results[$type_key] = $result;
}
return $results;
}
}
diff --git a/src/applications/people/typeahead/PhabricatorViewerDatasource.php b/src/applications/people/typeahead/PhabricatorViewerDatasource.php
index e29fd4586b..6f6d1181fe 100644
--- a/src/applications/people/typeahead/PhabricatorViewerDatasource.php
+++ b/src/applications/people/typeahead/PhabricatorViewerDatasource.php
@@ -1,81 +1,81 @@
<?php
final class PhabricatorViewerDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Viewer');
}
public function getPlaceholderText() {
return pht('Type viewer()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'viewer' => array(
'name' => pht('Current Viewer'),
'summary' => pht('Use the current viewing user.'),
'description' => pht(
"This function allows you to change the behavior of a query ".
"based on who is running it. When you use this function, you will ".
"be the current viewer, so it works like you typed your own ".
"username.\n\n".
"However, if you save a query using this function and send it ".
"to someone else, it will work like //their// username was the ".
"one that was typed. This can be useful for building dashboard ".
"panels that always show relevant information to the user who ".
"is looking at them."),
),
);
}
public function loadResults() {
if ($this->getViewer()->getPHID()) {
$results = array($this->renderViewerFunctionToken());
} else {
$results = array();
}
return $this->filterResultsAgainstTokens($results);
}
protected function canEvaluateFunction($function) {
if (!$this->getViewer()->getPHID()) {
return false;
}
return parent::canEvaluateFunction($function);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = $this->getViewer()->getPHID();
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$tokens = array();
foreach ($argv_list as $argv) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->renderViewerFunctionToken());
}
return $tokens;
}
private function renderViewerFunctionToken() {
return $this->newFunctionResult()
->setName(pht('Current Viewer'))
->setPHID('viewer()')
->setIcon('fa-user')
->setUnique(true)
->addAttribute(pht('Select current viewer.'));
}
}
diff --git a/src/applications/phame/editor/PhameBlogEditEngine.php b/src/applications/phame/editor/PhameBlogEditEngine.php
index e11dec6847..9238f7ea01 100644
--- a/src/applications/phame/editor/PhameBlogEditEngine.php
+++ b/src/applications/phame/editor/PhameBlogEditEngine.php
@@ -1,138 +1,138 @@
<?php
final class PhameBlogEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phame.blog';
public function getEngineName() {
return pht('Blogs');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Phame Blog Forms');
}
public function getSummaryText() {
return pht('Configure how blogs in Phame are created and edited.');
}
protected function newEditableObject() {
return PhameBlog::initializeNewBlog($this->getViewer());
}
protected function newObjectQuery() {
return id(new PhameBlogQuery())
->needProfileImage(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Blog');
}
protected function getObjectEditTitleText($object) {
return pht('Edit %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Blog');
}
protected function getObjectName() {
return pht('Blog');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('blog/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('blog/edit/');
}
protected function getObjectViewURI($object) {
return $object->getManageURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhameBlogCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Blog name.'))
->setConduitDescription(pht('Retitle the blog.'))
->setConduitTypeDescription(pht('New blog title.'))
->setTransactionType(PhameBlogNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('subtitle')
->setLabel(pht('Subtitle'))
->setDescription(pht('Blog subtitle.'))
->setConduitDescription(pht('Change the blog subtitle.'))
->setConduitTypeDescription(pht('New blog subtitle.'))
->setTransactionType(PhameBlogSubtitleTransaction::TRANSACTIONTYPE)
->setValue($object->getSubtitle()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Blog description.'))
->setConduitDescription(pht('Change the blog description.'))
->setConduitTypeDescription(pht('New blog description.'))
->setTransactionType(PhameBlogDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorTextEditField())
->setKey('domainFullURI')
->setLabel(pht('Full Domain URI'))
->setControlInstructions(pht('Set Full Domain URI if you plan to '.
'serve this blog on another hosted domain. Parent Site Name and '.
'Parent Site URI are optional but helpful since they provide '.
'a link from the blog back to your parent site.'))
->setDescription(pht('Blog full domain URI.'))
->setConduitDescription(pht('Change the blog full domain URI.'))
->setConduitTypeDescription(pht('New blog full domain URI.'))
->setValue($object->getDomainFullURI())
->setTransactionType(PhameBlogFullDomainTransaction::TRANSACTIONTYPE),
id(new PhabricatorTextEditField())
->setKey('parentSite')
->setLabel(pht('Parent Site Name'))
->setDescription(pht('Blog parent site name.'))
->setConduitDescription(pht('Change the blog parent site name.'))
->setConduitTypeDescription(pht('New blog parent site name.'))
->setValue($object->getParentSite())
->setTransactionType(PhameBlogParentSiteTransaction::TRANSACTIONTYPE),
id(new PhabricatorTextEditField())
->setKey('parentDomain')
->setLabel(pht('Parent Site URI'))
->setDescription(pht('Blog parent domain name.'))
->setConduitDescription(pht('Change the blog parent domain.'))
->setConduitTypeDescription(pht('New blog parent domain.'))
->setValue($object->getParentDomain())
->setTransactionType(PhameBlogParentDomainTransaction::TRANSACTIONTYPE),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setTransactionType(PhameBlogStatusTransaction::TRANSACTIONTYPE)
->setIsFormField(false)
->setOptions(PhameBlog::getStatusNameMap())
->setDescription(pht('Active or archived status.'))
->setConduitDescription(pht('Active or archive the blog.'))
->setConduitTypeDescription(pht('New blog status constant.'))
->setValue($object->getStatus()),
);
}
}
diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php
index 656ede95fe..eaf1389f17 100644
--- a/src/applications/phame/editor/PhameBlogEditor.php
+++ b/src/applications/phame/editor/PhameBlogEditor.php
@@ -1,111 +1,111 @@
<?php
final class PhameBlogEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phame Blogs');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this blog.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_INTERACT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->requireActor()->getPHID();
$phids[] = $object->getCreatorPHID();
return $phids;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject($name);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhameBlogReplyHandler())
->setMailReceiver($object);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addLinkSection(
pht('BLOG DETAIL'),
PhabricatorEnv::getProductionURI($object->getViewURI()));
return $body;
}
public function getMailTagsMap() {
return array(
PhameBlogTransaction::MAILTAG_DETAILS =>
pht("A blog's details change."),
PhameBlogTransaction::MAILTAG_SUBSCRIBERS =>
pht("A blog's subscribers change."),
PhameBlogTransaction::MAILTAG_OTHER =>
pht('Other blog activity not listed above occurs.'),
);
}
protected function getMailSubjectPrefix() {
return '[Phame]';
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldPhameBlogAdapter())
->setBlog($object);
}
}
diff --git a/src/applications/phame/editor/PhamePostEditEngine.php b/src/applications/phame/editor/PhamePostEditEngine.php
index 04738beb80..651f29b091 100644
--- a/src/applications/phame/editor/PhamePostEditEngine.php
+++ b/src/applications/phame/editor/PhamePostEditEngine.php
@@ -1,135 +1,135 @@
<?php
final class PhamePostEditEngine
extends PhabricatorEditEngine {
private $blog;
const ENGINECONST = 'phame.post';
public function getEngineName() {
return pht('Blog Posts');
}
public function getSummaryHeader() {
return pht('Configure Blog Post Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing blog posts in Phame.');
}
public function setBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
if ($this->blog) {
$blog = $this->blog;
} else {
$blog = PhameBlog::initializeNewBlog($viewer);
}
return PhamePost::initializePost($viewer, $blog);
}
protected function newObjectQuery() {
return new PhamePostQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Post');
}
protected function getObjectEditTitleText($object) {
return pht('Edit %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return $object->getTitle();
}
protected function getObjectCreateShortText() {
return pht('Create Post');
}
protected function getObjectName() {
return pht('Post');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('post/edit/');
}
protected function buildCustomEditFields($object) {
$blog_phid = $object->getBlog()->getPHID();
return array(
id(new PhabricatorHandlesEditField())
->setKey('blog')
->setLabel(pht('Blog'))
->setDescription(pht('Blog to publish this post to.'))
->setConduitDescription(
pht('Choose a blog to create a post on (or move a post to).'))
->setConduitTypeDescription(pht('PHID of the blog.'))
->setAliases(array('blogPHID'))
->setTransactionType(PhamePostBlogTransaction::TRANSACTIONTYPE)
->setHandleParameterType(new AphrontPHIDListHTTPParameterType())
->setSingleValue($blog_phid)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setIsLocked(true),
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Title'))
->setDescription(pht('Post title.'))
->setConduitDescription(pht('Retitle the post.'))
->setConduitTypeDescription(pht('New post title.'))
->setTransactionType(PhamePostTitleTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getTitle()),
id(new PhabricatorTextEditField())
->setKey('subtitle')
->setLabel(pht('Subtitle'))
->setDescription(pht('Post subtitle.'))
->setConduitDescription(pht('Change the post subtitle.'))
->setConduitTypeDescription(pht('New post subtitle.'))
->setTransactionType(PhamePostSubtitleTransaction::TRANSACTIONTYPE)
->setValue($object->getSubtitle()),
id(new PhabricatorSelectEditField())
->setKey('visibility')
->setLabel(pht('Visibility'))
->setDescription(pht('Post visibility.'))
->setConduitDescription(pht('Change post visibility.'))
->setConduitTypeDescription(pht('New post visibility constant.'))
->setTransactionType(PhamePostVisibilityTransaction::TRANSACTIONTYPE)
->setValue($object->getVisibility())
->setOptions(PhameConstants::getPhamePostStatusMap()),
id(new PhabricatorRemarkupEditField())
->setKey('body')
->setLabel(pht('Body'))
->setDescription(pht('Post body.'))
->setConduitDescription(pht('Change post body.'))
->setConduitTypeDescription(pht('New post body.'))
->setTransactionType(PhamePostBodyTransaction::TRANSACTIONTYPE)
->setValue($object->getBody())
->setPreviewPanel(
id(new PHUIRemarkupPreviewPanel())
->setHeader(pht('Blog Post'))
->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT)),
);
}
}
diff --git a/src/applications/phame/editor/PhamePostEditor.php b/src/applications/phame/editor/PhamePostEditor.php
index 61092114d1..60ea50aeec 100644
--- a/src/applications/phame/editor/PhamePostEditor.php
+++ b/src/applications/phame/editor/PhamePostEditor.php
@@ -1,142 +1,142 @@
<?php
final class PhamePostEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phame Posts');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this post.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_INTERACT_POLICY;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
if ($object->isDraft() || ($object->isArchived())) {
return false;
}
return true;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
if ($object->isDraft() || $object->isArchived()) {
return false;
}
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $object->getBloggerPHID();
$phids[] = $this->requireActor()->getPHID();
$blog_phid = $object->getBlogPHID();
if ($blog_phid) {
$cc_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
$blog_phid);
foreach ($cc_phids as $cc) {
$phids[] = $cc;
}
}
return $phids;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$title = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject($title);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhamePostReplyHandler())
->setMailReceiver($object);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
// We don't send mail if the object is a draft, and we only want
// to include the full body of the post on the either the
// first creation or if it was created as a draft, once it goes live.
if ($this->getIsNewObject()) {
$body->addRemarkupSection(null, $object->getBody());
} else {
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhamePostVisibilityTransaction::TRANSACTIONTYPE:
if (!$object->isDraft() && !$object->isArchived()) {
$body->addRemarkupSection(null, $object->getBody());
}
break;
}
}
}
$body->addLinkSection(
pht('POST DETAIL'),
PhabricatorEnv::getProductionURI($object->getViewURI()));
return $body;
}
public function getMailTagsMap() {
return array(
PhamePostTransaction::MAILTAG_CONTENT =>
pht("A post's content changes."),
PhamePostTransaction::MAILTAG_SUBSCRIBERS =>
pht("A post's subscribers change."),
PhamePostTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a post.'),
PhamePostTransaction::MAILTAG_OTHER =>
pht('Other post activity not listed above occurs.'),
);
}
protected function getMailSubjectPrefix() {
return '[Phame]';
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldPhamePostAdapter())
->setPost($object);
}
}
diff --git a/src/applications/phame/herald/HeraldPhameBlogAdapter.php b/src/applications/phame/herald/HeraldPhameBlogAdapter.php
index d9368a97d2..160387d24c 100644
--- a/src/applications/phame/herald/HeraldPhameBlogAdapter.php
+++ b/src/applications/phame/herald/HeraldPhameBlogAdapter.php
@@ -1,55 +1,55 @@
<?php
final class HeraldPhameBlogAdapter extends HeraldAdapter {
private $blog;
protected function newObject() {
return new PhameBlog();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to Phame Blogs being created or updated.');
}
protected function initializeNewAdapter() {
$this->blog = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setBlog(PhameBlog $blog) {
$this->blog = $blog;
return $this;
}
public function getObject() {
return $this->blog;
}
public function getAdapterContentName() {
return pht('Phame Blogs');
}
public function getHeraldName() {
return 'BLOG'.$this->getObject()->getID();
}
}
diff --git a/src/applications/phame/herald/HeraldPhamePostAdapter.php b/src/applications/phame/herald/HeraldPhamePostAdapter.php
index 72e7124271..f9446c6866 100644
--- a/src/applications/phame/herald/HeraldPhamePostAdapter.php
+++ b/src/applications/phame/herald/HeraldPhamePostAdapter.php
@@ -1,55 +1,55 @@
<?php
final class HeraldPhamePostAdapter extends HeraldAdapter {
private $post;
protected function newObject() {
return new PhamePost();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to Phame Posts being created or updated.');
}
protected function initializeNewAdapter() {
$this->post = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setPost(PhamePost $post) {
$this->post = $post;
return $this;
}
public function getObject() {
return $this->post;
}
public function getAdapterContentName() {
return pht('Phame Posts');
}
public function getHeraldName() {
return 'POST'.$this->getObject()->getID();
}
}
diff --git a/src/applications/phame/phid/PhabricatorPhameBlogPHIDType.php b/src/applications/phame/phid/PhabricatorPhameBlogPHIDType.php
index 905f4b893b..ccca276032 100644
--- a/src/applications/phame/phid/PhabricatorPhameBlogPHIDType.php
+++ b/src/applications/phame/phid/PhabricatorPhameBlogPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorPhameBlogPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'BLOG';
public function getTypeName() {
return pht('Phame Blog');
}
public function newObject() {
return new PhameBlog();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhameBlogQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$blog = $objects[$phid];
$handle->setName($blog->getName());
$handle->setFullName($blog->getName());
$handle->setURI('/phame/blog/view/'.$blog->getID().'/');
if ($blog->isArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/phame/phid/PhabricatorPhamePostPHIDType.php b/src/applications/phame/phid/PhabricatorPhamePostPHIDType.php
index 7c86d89d41..174043d206 100644
--- a/src/applications/phame/phid/PhabricatorPhamePostPHIDType.php
+++ b/src/applications/phame/phid/PhabricatorPhamePostPHIDType.php
@@ -1,46 +1,46 @@
<?php
final class PhabricatorPhamePostPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'POST';
public function getTypeName() {
return pht('Phame Post');
}
public function newObject() {
return new PhamePost();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhamePostQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$post = $objects[$phid];
$handle->setName($post->getTitle());
$handle->setFullName(pht('Blog Post: ').$post->getTitle());
$handle->setURI('/J'.$post->getID());
if ($post->isArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/phame/query/PhameBlogSearchEngine.php b/src/applications/phame/query/PhameBlogSearchEngine.php
index eaef32af1c..4b8c287173 100644
--- a/src/applications/phame/query/PhameBlogSearchEngine.php
+++ b/src/applications/phame/query/PhameBlogSearchEngine.php
@@ -1,115 +1,115 @@
<?php
final class PhameBlogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phame Blogs');
}
public function getApplicationClassName() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function newQuery() {
return id(new PhameBlogQuery())
->needProfileImage(true);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses(array($map['statuses']));
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchSelectField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(array(
'' => pht('All'),
PhameBlog::STATUS_ACTIVE => pht('Active'),
PhameBlog::STATUS_ARCHIVED => pht('Archived'),
)),
);
}
protected function getURI($path) {
return '/phame/blog/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Blogs'),
'archived' => pht('Archived Blogs'),
'all' => pht('All Blogs'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query->setParameter(
'statuses', PhameBlog::STATUS_ACTIVE);
case 'archived':
return $query->setParameter(
'statuses', PhameBlog::STATUS_ARCHIVED);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $blogs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($blogs, 'PhameBlog');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($blogs as $blog) {
$id = $blog->getID();
if ($blog->getDomain()) {
$domain = $blog->getDomain();
} else {
$domain = pht('Local Blog');
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($blog)
->setHeader($blog->getName())
->setImageURI($blog->getProfileImageURI())
->setDisabled($blog->isArchived())
->setHref($this->getApplicationURI("/blog/view/{$id}/"))
->addAttribute($domain);
if (!$blog->isArchived()) {
$button = id(new PHUIButtonView())
->setTag('a')
->setText('New Post')
->setHref($this->getApplicationURI('/post/edit/?blog='.$id))
->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE);
$item->setSideColumn($button);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No blogs found.'));
return $result;
}
}
diff --git a/src/applications/phame/query/PhamePostSearchEngine.php b/src/applications/phame/query/PhamePostSearchEngine.php
index d1d9a791ec..1cff6d1891 100644
--- a/src/applications/phame/query/PhamePostSearchEngine.php
+++ b/src/applications/phame/query/PhamePostSearchEngine.php
@@ -1,142 +1,142 @@
<?php
final class PhamePostSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phame Posts');
}
public function getApplicationClassName() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function newQuery() {
return new PhamePostQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['visibility']) {
$query->withVisibility($map['visibility']);
}
if ($map['blogPHIDs']) {
$query->withBlogPHIDs($map['blogPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchCheckboxesField())
->setKey('visibility')
->setLabel(pht('Visibility'))
->setOptions(
array(
PhameConstants::VISIBILITY_PUBLISHED => pht('Published'),
PhameConstants::VISIBILITY_DRAFT => pht('Draft'),
PhameConstants::VISIBILITY_ARCHIVED => pht('Archived'),
)),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Blogs'))
->setKey('blogPHIDs')
->setAliases(array('blog', 'blogs', 'blogPHIDs'))
->setDescription(
pht('Search for posts within certain blogs.'))
->setDatasource(new PhameBlogDatasource()),
);
}
protected function getURI($path) {
return '/phame/post/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Posts'),
'live' => pht('Published Posts'),
'draft' => pht('Draft Posts'),
'archived' => pht('Archived Posts'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'live':
return $query->setParameter(
'visibility', array(PhameConstants::VISIBILITY_PUBLISHED));
case 'draft':
return $query->setParameter(
'visibility', array(PhameConstants::VISIBILITY_DRAFT));
case 'archived':
return $query->setParameter(
'visibility', array(PhameConstants::VISIBILITY_ARCHIVED));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $posts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($posts, 'PhamePost');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($posts as $post) {
$id = $post->getID();
$blog = $post->getBlog();
$blog_name = $viewer->renderHandle($post->getBlogPHID())->render();
$blog_name = pht('Blog: %s', $blog_name);
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($post)
->setObjectName($post->getMonogram())
->setHeader($post->getTitle())
->setStatusIcon('fa-star')
->setHref($post->getViewURI())
->addAttribute($blog_name);
if ($post->isDraft()) {
$item->setStatusIcon('fa-star-o grey');
$item->setDisabled(true);
$item->addIcon('fa-star-o', pht('Draft Post'));
} else if ($post->isArchived()) {
$item->setStatusIcon('fa-ban grey');
$item->setDisabled(true);
$item->addIcon('fa-ban', pht('Archived Post'));
} else {
$date = $post->getDatePublished();
$item->setEpoch($date);
}
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-pencil')
->setHref($post->getEditURI()));
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No blogs posts found.'));
return $result;
}
}
diff --git a/src/applications/phame/typeahead/PhameBlogDatasource.php b/src/applications/phame/typeahead/PhameBlogDatasource.php
index 0658dec3b9..87d673b544 100644
--- a/src/applications/phame/typeahead/PhameBlogDatasource.php
+++ b/src/applications/phame/typeahead/PhameBlogDatasource.php
@@ -1,53 +1,53 @@
<?php
final class PhameBlogDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Blogs');
}
public function getPlaceholderText() {
return pht('Type a blog name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPhameApplication';
+ return PhabricatorPhameApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$blogs = id(new PhameBlogQuery())
->setViewer($viewer)
->needProfileImage(true)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->execute();
$results = array();
foreach ($blogs as $blog) {
$closed = null;
$status = $blog->getStatus();
if ($status === PhabricatorBadgesBadge::STATUS_ARCHIVED) {
$closed = pht('Archived');
}
$results[] = id(new PhabricatorTypeaheadResult())
->setName($blog->getName())
->setClosed($closed)
->addAttribute(pht('Phame Blog'))
->setImageURI($blog->getProfileImageURI())
->setPHID($blog->getPHID());
}
$results = $this->filterResultsAgainstTokens($results);
return $results;
}
}
diff --git a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
index 93d8a47de7..d38d65f1a4 100644
--- a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
+++ b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
@@ -1,44 +1,44 @@
<?php
final class PhabricatorMetaMTAApplicationEmailPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'APPE';
public function getTypeName() {
return pht('Application Email');
}
public function getTypeIcon() {
return 'fa-email bluegrey';
}
public function newObject() {
return new PhabricatorMetaMTAApplicationEmail();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorMetaMTAApplication';
+ return PhabricatorMetaMTAApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMetaMTAApplicationEmailQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$email = $objects[$phid];
$handle->setName($email->getAddress());
$handle->setFullName($email->getAddress());
}
}
}
diff --git a/src/applications/phlux/editor/PhluxVariableEditor.php b/src/applications/phlux/editor/PhluxVariableEditor.php
index 2e36ba8162..5784d19d80 100644
--- a/src/applications/phlux/editor/PhluxVariableEditor.php
+++ b/src/applications/phlux/editor/PhluxVariableEditor.php
@@ -1,72 +1,72 @@
<?php
final class PhluxVariableEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhluxApplication';
+ return PhabricatorPhluxApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phlux Variables');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhluxTransaction::TYPE_EDIT_KEY;
$types[] = PhluxTransaction::TYPE_EDIT_VALUE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
return $object->getVariableKey();
case PhluxTransaction::TYPE_EDIT_VALUE:
return $object->getVariableValue();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
case PhluxTransaction::TYPE_EDIT_VALUE:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
$object->setVariableKey($xaction->getNewValue());
return;
case PhluxTransaction::TYPE_EDIT_VALUE:
$object->setVariableValue($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhluxTransaction::TYPE_EDIT_KEY:
case PhluxTransaction::TYPE_EDIT_VALUE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
}
diff --git a/src/applications/phlux/phid/PhluxVariablePHIDType.php b/src/applications/phlux/phid/PhluxVariablePHIDType.php
index 97525c4052..89e244ee75 100644
--- a/src/applications/phlux/phid/PhluxVariablePHIDType.php
+++ b/src/applications/phlux/phid/PhluxVariablePHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhluxVariablePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PVAR';
public function getTypeName() {
return pht('Variable');
}
public function newObject() {
return new PhluxVariable();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhluxApplication';
+ return PhabricatorPhluxApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhluxVariableQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$variable = $objects[$phid];
$key = $variable->getVariableKey();
$handle->setName($key);
$handle->setFullName(pht('Variable "%s"', $key));
$handle->setURI("/phlux/view/{$key}/");
}
}
}
diff --git a/src/applications/phlux/query/PhluxVariableQuery.php b/src/applications/phlux/query/PhluxVariableQuery.php
index 8ec4bc9334..27ffd9875f 100644
--- a/src/applications/phlux/query/PhluxVariableQuery.php
+++ b/src/applications/phlux/query/PhluxVariableQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhluxVariableQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $keys;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
protected function loadPage() {
$table = new PhluxVariable();
$conn_r = $table->establishConnection('r');
$rows = 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($rows);
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->keys !== null) {
$where[] = qsprintf(
$conn,
'variableKey IN (%Ls)',
$this->keys);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
protected function getDefaultOrderVector() {
return array('key');
}
public function getOrderableColumns() {
return array(
'key' => array(
'column' => 'variableKey',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'key' => $object->getVariableKey(),
);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhluxApplication';
+ return PhabricatorPhluxApplication::class;
}
}
diff --git a/src/applications/pholio/editor/PholioMockEditor.php b/src/applications/pholio/editor/PholioMockEditor.php
index df5d55672c..6eeb83c1bd 100644
--- a/src/applications/pholio/editor/PholioMockEditor.php
+++ b/src/applications/pholio/editor/PholioMockEditor.php
@@ -1,244 +1,244 @@
<?php
final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
private $images = array();
public function getEditorApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Pholio Mocks');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this mock.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PholioReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}");
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$viewer = $this->requireActor();
$body = id(new PhabricatorMetaMTAMailBody())
->setViewer($viewer);
$mock_uri = $object->getURI();
$mock_uri = PhabricatorEnv::getProductionURI($mock_uri);
$this->addHeadersAndCommentsToMailBody(
$body,
$xactions,
pht('View Mock'),
$mock_uri);
$type_inline = PholioMockInlineTransaction::TRANSACTIONTYPE;
$inlines = array();
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() == $type_inline) {
$inlines[] = $xaction;
}
}
$this->appendInlineCommentsForMail($object, $inlines, $body);
$body->addLinkSection(
pht('MOCK DETAIL'),
PhabricatorEnv::getProductionURI($object->getURI()));
return $body;
}
private function appendInlineCommentsForMail(
$object,
array $inlines,
PhabricatorMetaMTAMailBody $body) {
if (!$inlines) {
return;
}
$viewer = $this->requireActor();
$header = pht('INLINE COMMENTS');
$body->addRawPlaintextSection($header);
$body->addRawHTMLSection(phutil_tag('strong', array(), $header));
$image_ids = array();
foreach ($inlines as $inline) {
$comment = $inline->getComment();
$image_id = $comment->getImageID();
$image_ids[$image_id] = $image_id;
}
$images = id(new PholioImageQuery())
->setViewer($viewer)
->withIDs($image_ids)
->execute();
$images = mpull($images, null, 'getID');
foreach ($inlines as $inline) {
$comment = $inline->getComment();
$content = $comment->getContent();
$image_id = $comment->getImageID();
$image = idx($images, $image_id);
if ($image) {
$image_name = $image->getName();
} else {
$image_name = pht('Unknown (ID %d)', $image_id);
}
$body->addRemarkupSection(
pht('Image "%s":', $image_name),
$content);
}
}
protected function getMailSubjectPrefix() {
return pht('[Pholio]');
}
public function getMailTagsMap() {
return array(
PholioTransaction::MAILTAG_STATUS =>
pht("A mock's status changes."),
PholioTransaction::MAILTAG_COMMENT =>
pht('Someone comments on a mock.'),
PholioTransaction::MAILTAG_UPDATED =>
pht('Mock images or descriptions change.'),
PholioTransaction::MAILTAG_OTHER =>
pht('Other mock activity not listed above occurs.'),
);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldPholioMockAdapter())
->setMock($object);
}
protected function sortTransactions(array $xactions) {
$head = array();
$tail = array();
// Move inline comments to the end, so the comments precede them.
foreach ($xactions as $xaction) {
$type = $xaction->getTransactionType();
if ($type == PholioMockInlineTransaction::TRANSACTIONTYPE) {
$tail[] = $xaction;
} else {
$head[] = $xaction;
}
}
return array_values(array_merge($head, $tail));
}
protected function shouldImplyCC(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioMockInlineTransaction::TRANSACTIONTYPE:
return true;
}
return parent::shouldImplyCC($object, $xaction);
}
public function loadPholioImage($object, $phid) {
if (!isset($this->images[$phid])) {
$image = id(new PholioImageQuery())
->setViewer($this->getActor())
->withPHIDs(array($phid))
->executeOne();
if (!$image) {
throw new Exception(
pht(
'No image exists with PHID "%s".',
$phid));
}
$mock_phid = $image->getMockPHID();
if ($mock_phid) {
if ($mock_phid !== $object->getPHID()) {
throw new Exception(
pht(
'Image ("%s") belongs to the wrong object ("%s", expected "%s").',
$phid,
$mock_phid,
$object->getPHID()));
}
}
$this->images[$phid] = $image;
}
return $this->images[$phid];
}
}
diff --git a/src/applications/pholio/herald/HeraldPholioMockAdapter.php b/src/applications/pholio/herald/HeraldPholioMockAdapter.php
index 5520a60cdc..ed1d2daea1 100644
--- a/src/applications/pholio/herald/HeraldPholioMockAdapter.php
+++ b/src/applications/pholio/herald/HeraldPholioMockAdapter.php
@@ -1,69 +1,69 @@
<?php
final class HeraldPholioMockAdapter extends HeraldAdapter {
private $mock;
public function getAdapterApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to mocks being created or updated.');
}
protected function initializeNewAdapter() {
$this->mock = $this->newObject();
}
protected function newObject() {
return new PholioMock();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PholioMock);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when a mock is created or updated.');
}
public function setObject($object) {
$this->mock = $object;
return $this;
}
public function getObject() {
return $this->mock;
}
public function setMock(PholioMock $mock) {
$this->mock = $mock;
return $this;
}
public function getMock() {
return $this->mock;
}
public function getAdapterContentName() {
return pht('Pholio Mocks');
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function getHeraldName() {
return 'M'.$this->getMock()->getID();
}
}
diff --git a/src/applications/pholio/phid/PholioImagePHIDType.php b/src/applications/pholio/phid/PholioImagePHIDType.php
index d7a9984fd5..ffbb3f71bf 100644
--- a/src/applications/pholio/phid/PholioImagePHIDType.php
+++ b/src/applications/pholio/phid/PholioImagePHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PholioImagePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PIMG';
public function getTypeName() {
return pht('Image');
}
public function newObject() {
return new PholioImage();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PholioImageQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$image = $objects[$phid];
$handle
->setName($image->getName())
->setURI($image->getURI());
}
}
}
diff --git a/src/applications/pholio/phid/PholioMockPHIDType.php b/src/applications/pholio/phid/PholioMockPHIDType.php
index 13ee4cb81f..bfdecae90d 100644
--- a/src/applications/pholio/phid/PholioMockPHIDType.php
+++ b/src/applications/pholio/phid/PholioMockPHIDType.php
@@ -1,77 +1,77 @@
<?php
final class PholioMockPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'MOCK';
public function getTypeName() {
return pht('Pholio Mock');
}
public function newObject() {
return new PholioMock();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PholioMockQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$mock = $objects[$phid];
$id = $mock->getID();
$name = $mock->getName();
$handle->setURI("/M{$id}");
$handle->setName("M{$id}");
$handle->setFullName("M{$id}: {$name}");
if ($mock->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^M\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PholioMockQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/pholio/query/PholioImageQuery.php b/src/applications/pholio/query/PholioImageQuery.php
index 69d890ab98..44bee77205 100644
--- a/src/applications/pholio/query/PholioImageQuery.php
+++ b/src/applications/pholio/query/PholioImageQuery.php
@@ -1,158 +1,158 @@
<?php
final class PholioImageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $mockPHIDs;
private $mocks;
private $needInlineComments;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMocks(array $mocks) {
assert_instances_of($mocks, 'PholioMock');
$mocks = mpull($mocks, null, 'getPHID');
$this->mocks = $mocks;
$this->mockPHIDs = array_keys($mocks);
return $this;
}
public function withMockPHIDs(array $mock_phids) {
$this->mockPHIDs = $mock_phids;
return $this;
}
public function needInlineComments($need_inline_comments) {
$this->needInlineComments = $need_inline_comments;
return $this;
}
public function newResultObject() {
return new PholioImage();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->mockPHIDs !== null) {
$where[] = qsprintf(
$conn,
'mockPHID IN (%Ls)',
$this->mockPHIDs);
}
return $where;
}
protected function willFilterPage(array $images) {
assert_instances_of($images, 'PholioImage');
$mock_phids = array();
foreach ($images as $image) {
if (!$image->hasMock()) {
continue;
}
$mock_phids[] = $image->getMockPHID();
}
if ($mock_phids) {
if ($this->mocks) {
$mocks = $this->mocks;
} else {
$mocks = id(new PholioMockQuery())
->setViewer($this->getViewer())
->withPHIDs($mock_phids)
->execute();
}
$mocks = mpull($mocks, null, 'getPHID');
foreach ($images as $key => $image) {
if (!$image->hasMock()) {
continue;
}
$mock = idx($mocks, $image->getMockPHID());
if (!$mock) {
unset($images[$key]);
$this->didRejectResult($image);
continue;
}
$image->attachMock($mock);
}
}
return $images;
}
protected function didFilterPage(array $images) {
assert_instances_of($images, 'PholioImage');
$file_phids = mpull($images, 'getFilePHID');
$all_files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$all_files = mpull($all_files, null, 'getPHID');
if ($this->needInlineComments) {
// Only load inline comments the viewer has permission to see.
$all_inline_comments = id(new PholioTransactionComment())->loadAllWhere(
'imageID IN (%Ld)
AND (transactionPHID IS NOT NULL OR authorPHID = %s)',
mpull($images, 'getID'),
$this->getViewer()->getPHID());
$all_inline_comments = mgroup($all_inline_comments, 'getImageID');
}
foreach ($images as $image) {
$file = idx($all_files, $image->getFilePHID());
if (!$file) {
$file = PhabricatorFile::loadBuiltin($this->getViewer(), 'missing.png');
}
$image->attachFile($file);
if ($this->needInlineComments) {
$inlines = idx($all_inline_comments, $image->getID(), array());
$image->attachInlineComments($inlines);
}
}
return $images;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
}
diff --git a/src/applications/pholio/query/PholioMockQuery.php b/src/applications/pholio/query/PholioMockQuery.php
index 4820ffd8eb..24d56a3b33 100644
--- a/src/applications/pholio/query/PholioMockQuery.php
+++ b/src/applications/pholio/query/PholioMockQuery.php
@@ -1,162 +1,162 @@
<?php
final class PholioMockQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $statuses;
private $needCoverFiles;
private $needImages;
private $needInlineComments;
private $needTokenCounts;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needCoverFiles($need_cover_files) {
$this->needCoverFiles = $need_cover_files;
return $this;
}
public function needImages($need_images) {
$this->needImages = $need_images;
return $this;
}
public function needInlineComments($need_inline_comments) {
$this->needInlineComments = $need_inline_comments;
return $this;
}
public function needTokenCounts($need) {
$this->needTokenCounts = $need;
return $this;
}
public function newResultObject() {
return new PholioMock();
}
protected function loadPage() {
if ($this->needInlineComments && !$this->needImages) {
throw new Exception(
pht(
'You can not query for inline comments without also querying for '.
'images.'));
}
return $this->loadStandardPage(new PholioMock());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'mock.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'mock.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'mock.authorPHID in (%Ls)',
$this->authorPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'mock.status IN (%Ls)',
$this->statuses);
}
return $where;
}
protected function didFilterPage(array $mocks) {
$viewer = $this->getViewer();
if ($this->needImages) {
$images = id(new PholioImageQuery())
->setViewer($viewer)
->withMocks($mocks)
->needInlineComments($this->needInlineComments)
->execute();
$image_groups = mgroup($images, 'getMockPHID');
foreach ($mocks as $mock) {
$images = idx($image_groups, $mock->getPHID(), array());
$mock->attachImages($images);
}
}
if ($this->needCoverFiles) {
$cover_files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(mpull($mocks, 'getCoverPHID'))
->execute();
$cover_files = mpull($cover_files, null, 'getPHID');
foreach ($mocks as $mock) {
$file = idx($cover_files, $mock->getCoverPHID());
if (!$file) {
$file = PhabricatorFile::loadBuiltin(
$viewer,
'missing.png');
}
$mock->attachCoverFile($file);
}
}
if ($this->needTokenCounts) {
$counts = id(new PhabricatorTokenCountQuery())
->withObjectPHIDs(mpull($mocks, 'getPHID'))
->execute();
foreach ($mocks as $mock) {
$token_count = idx($counts, $mock->getPHID(), 0);
$mock->attachTokenCount($token_count);
}
}
return $mocks;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
protected function getPrimaryTableAlias() {
return 'mock';
}
}
diff --git a/src/applications/pholio/query/PholioMockSearchEngine.php b/src/applications/pholio/query/PholioMockSearchEngine.php
index cbb175b2de..104533eee2 100644
--- a/src/applications/pholio/query/PholioMockSearchEngine.php
+++ b/src/applications/pholio/query/PholioMockSearchEngine.php
@@ -1,153 +1,153 @@
<?php
final class PholioMockSearchEngine extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Pholio Mocks');
}
public function getApplicationClassName() {
- return 'PhabricatorPholioApplication';
+ return PhabricatorPholioApplication::class;
}
public function newQuery() {
return id(new PholioMockQuery())
->needCoverFiles(true)
->needImages(true)
->needTokenCounts(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setKey('authorPHIDs')
->setAliases(array('authors'))
->setLabel(pht('Authors')),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(
id(new PholioMock())
->getStatuses()),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function getURI($path) {
return '/pholio/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'open' => pht('Open Mocks'),
'all' => pht('All Mocks'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'open':
return $query->setParameter(
'statuses',
array('open'));
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $mocks,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($mocks, 'PholioMock');
$viewer = $this->requireViewer();
$handles = $viewer->loadHandles(mpull($mocks, 'getAuthorPHID'));
$xform = PhabricatorFileTransform::getTransformByKey(
PhabricatorFileThumbnailTransform::TRANSFORM_PINBOARD);
$board = new PHUIPinboardView();
foreach ($mocks as $mock) {
$image = $mock->getCoverFile();
$image_uri = $image->getURIForTransform($xform);
list($x, $y) = $xform->getTransformedDimensions($image);
$header = 'M'.$mock->getID().' '.$mock->getName();
$item = id(new PHUIPinboardItemView())
->setUser($viewer)
->setHeader($header)
->setObject($mock)
->setURI('/M'.$mock->getID())
->setImageURI($image_uri)
->setImageSize($x, $y)
->setDisabled($mock->isClosed())
->addIconCount('fa-picture-o', count($mock->getActiveImages()))
->addIconCount('fa-trophy', $mock->getTokenCount());
if ($mock->getAuthorPHID()) {
$author_handle = $handles[$mock->getAuthorPHID()];
$datetime = phabricator_date($mock->getDateCreated(), $viewer);
$item->appendChild(
pht('By %s on %s', $author_handle->renderLink(), $datetime));
}
$board->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($board);
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Mock'))
->setHref('/pholio/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Upload sets of images for review with revision history and '.
'inline comments.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/phortune/editor/PhortuneAccountEditEngine.php b/src/applications/phortune/editor/PhortuneAccountEditEngine.php
index d7272965c2..20df9d16d9 100644
--- a/src/applications/phortune/editor/PhortuneAccountEditEngine.php
+++ b/src/applications/phortune/editor/PhortuneAccountEditEngine.php
@@ -1,131 +1,131 @@
<?php
final class PhortuneAccountEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phortune.account';
public function getEngineName() {
return pht('Phortune Accounts');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Phortune Account Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Phortune Accounts.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return PhortuneAccount::initializeNewAccount($this->getViewer());
}
protected function newObjectQuery() {
return new PhortuneAccountQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Payment Account');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Account: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Account');
}
protected function getObjectName() {
return pht('Account');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
if ($this->getIsCreate()) {
return $object->getURI();
} else {
return $object->getDetailsURI();
}
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
if ($this->getIsCreate()) {
$member_phids = array($viewer->getPHID());
} else {
$member_phids = $object->getMemberPHIDs();
}
$fields = array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Account name.'))
->setConduitTypeDescription(pht('New account name.'))
->setTransactionType(
PhortuneAccountNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName())
->setIsRequired(true),
id(new PhabricatorUsersEditField())
->setKey('managers')
->setAliases(array('memberPHIDs', 'managerPHIDs'))
->setLabel(pht('Managers'))
->setUseEdgeTransactions(true)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhortuneAccountHasMemberEdgeType::EDGECONST)
->setDescription(pht('Initial account managers.'))
->setConduitDescription(pht('Set account managers.'))
->setConduitTypeDescription(pht('New list of managers.'))
->setInitialValue($object->getMemberPHIDs())
->setValue($member_phids),
id(new PhabricatorTextEditField())
->setKey('billingName')
->setLabel(pht('Billing Name'))
->setDescription(pht('Account name for billing purposes.'))
->setConduitTypeDescription(pht('New account billing name.'))
->setTransactionType(
PhortuneAccountBillingNameTransaction::TRANSACTIONTYPE)
->setValue($object->getBillingName()),
id(new PhabricatorTextAreaEditField())
->setKey('billingAddress')
->setLabel(pht('Billing Address'))
->setDescription(pht('Account billing address.'))
->setConduitTypeDescription(pht('New account billing address.'))
->setTransactionType(
PhortuneAccountBillingAddressTransaction::TRANSACTIONTYPE)
->setValue($object->getBillingAddress()),
);
return $fields;
}
}
diff --git a/src/applications/phortune/editor/PhortuneAccountEditor.php b/src/applications/phortune/editor/PhortuneAccountEditor.php
index 8344bc2b6e..534c701616 100644
--- a/src/applications/phortune/editor/PhortuneAccountEditor.php
+++ b/src/applications/phortune/editor/PhortuneAccountEditor.php
@@ -1,82 +1,82 @@
<?php
final class PhortuneAccountEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Accounts');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this payment account.', $author);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$viewer = $this->requireActor();
switch ($type) {
case PhabricatorTransactions::TYPE_EDGE:
foreach ($xactions as $xaction) {
switch ($xaction->getMetadataValue('edge:type')) {
case PhortuneAccountHasMemberEdgeType::EDGECONST:
$old = $object->getMemberPHIDs();
$new = $this->getPHIDTransactionNewValue($xaction, $old);
$old = array_fuse($old);
$new = array_fuse($new);
foreach ($new as $new_phid) {
if (isset($old[$new_phid])) {
continue;
}
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($new_phid))
->executeOne();
if (!$user) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Account managers must be valid users, "%s" is not.',
$new_phid));
$errors[] = $error;
continue;
}
}
$actor_phid = $this->getActingAsPHID();
if (isset($old[$actor_phid]) && !isset($new[$actor_phid])) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('You can not remove yourself as an account manager.'),
$xaction);
$errors[] = $error;
}
break;
}
}
break;
}
return $errors;
}
}
diff --git a/src/applications/phortune/editor/PhortuneAccountEmailEditEngine.php b/src/applications/phortune/editor/PhortuneAccountEmailEditEngine.php
index c732e4215f..9bfed006b1 100644
--- a/src/applications/phortune/editor/PhortuneAccountEmailEditEngine.php
+++ b/src/applications/phortune/editor/PhortuneAccountEmailEditEngine.php
@@ -1,114 +1,114 @@
<?php
final class PhortuneAccountEmailEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phortune.account.email';
private $account;
public function setAccount(PhortuneAccount $account) {
$this->account = $account;
return $this;
}
public function getAccount() {
return $this->account;
}
public function getEngineName() {
return pht('Phortune Account Emails');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Phortune Account Email Forms');
}
public function getSummaryText() {
return pht(
'Configure creation and editing forms for Phortune Account '.
'Email Addresses.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
$account = $this->getAccount();
if (!$account) {
$account = new PhortuneAccount();
}
return PhortuneAccountEmail::initializeNewAddress(
$account,
$viewer->getPHID());
}
protected function newObjectQuery() {
return new PhortuneAccountEmailQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Add Email Address');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Account Email: %s', $object->getAddress());
}
protected function getObjectEditShortText($object) {
return pht('%s', $object->getAddress());
}
protected function getObjectCreateShortText() {
return pht('Add Email Address');
}
protected function getObjectName() {
return pht('Account Email');
}
protected function getObjectCreateCancelURI($object) {
return $this->getAccount()->getEmailAddressesURI();
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('address/edit/');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
if ($this->getIsCreate()) {
$address_field = id(new PhabricatorTextEditField())
->setTransactionType(
PhortuneAccountEmailAddressTransaction::TRANSACTIONTYPE)
->setIsRequired(true);
} else {
$address_field = new PhabricatorStaticEditField();
}
$address_field
->setKey('address')
->setLabel(pht('Email Address'))
->setDescription(pht('Email address.'))
->setConduitTypeDescription(pht('New email address.'))
->setValue($object->getAddress());
return array(
$address_field,
);
}
}
diff --git a/src/applications/phortune/editor/PhortuneAccountEmailEditor.php b/src/applications/phortune/editor/PhortuneAccountEmailEditor.php
index 40d12a97ba..986d8cdbb6 100644
--- a/src/applications/phortune/editor/PhortuneAccountEmailEditor.php
+++ b/src/applications/phortune/editor/PhortuneAccountEmailEditor.php
@@ -1,36 +1,36 @@
<?php
final class PhortuneAccountEmailEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Account Emails');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this account email.', $author);
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
PhortuneAccountEmailAddressTransaction::TRANSACTIONTYPE,
pht('Duplicate'),
pht(
'The email address "%s" is already attached to this account.',
$object->getAddress()),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
}
diff --git a/src/applications/phortune/editor/PhortuneCartEditor.php b/src/applications/phortune/editor/PhortuneCartEditor.php
index aef59f059a..72d7ba6ef9 100644
--- a/src/applications/phortune/editor/PhortuneCartEditor.php
+++ b/src/applications/phortune/editor/PhortuneCartEditor.php
@@ -1,347 +1,347 @@
<?php
final class PhortuneCartEditor
extends PhabricatorApplicationTransactionEditor {
private $invoiceIssues;
public function setInvoiceIssues(array $invoice_issues) {
$this->invoiceIssues = $invoice_issues;
return $this;
}
public function getInvoiceIssues() {
return $this->invoiceIssues;
}
public function isInvoice() {
return (bool)$this->invoiceIssues;
}
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Carts');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhortuneCartTransaction::TYPE_CREATED;
$types[] = PhortuneCartTransaction::TYPE_PURCHASED;
$types[] = PhortuneCartTransaction::TYPE_HOLD;
$types[] = PhortuneCartTransaction::TYPE_REVIEW;
$types[] = PhortuneCartTransaction::TYPE_CANCEL;
$types[] = PhortuneCartTransaction::TYPE_REFUND;
$types[] = PhortuneCartTransaction::TYPE_INVOICED;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneCartTransaction::TYPE_CREATED:
case PhortuneCartTransaction::TYPE_PURCHASED:
case PhortuneCartTransaction::TYPE_HOLD:
case PhortuneCartTransaction::TYPE_REVIEW:
case PhortuneCartTransaction::TYPE_CANCEL:
case PhortuneCartTransaction::TYPE_REFUND:
case PhortuneCartTransaction::TYPE_INVOICED:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneCartTransaction::TYPE_CREATED:
case PhortuneCartTransaction::TYPE_PURCHASED:
case PhortuneCartTransaction::TYPE_HOLD:
case PhortuneCartTransaction::TYPE_REVIEW:
case PhortuneCartTransaction::TYPE_CANCEL:
case PhortuneCartTransaction::TYPE_REFUND:
case PhortuneCartTransaction::TYPE_INVOICED:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneCartTransaction::TYPE_CREATED:
case PhortuneCartTransaction::TYPE_PURCHASED:
case PhortuneCartTransaction::TYPE_HOLD:
case PhortuneCartTransaction::TYPE_REVIEW:
case PhortuneCartTransaction::TYPE_CANCEL:
case PhortuneCartTransaction::TYPE_REFUND:
case PhortuneCartTransaction::TYPE_INVOICED:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneCartTransaction::TYPE_CREATED:
case PhortuneCartTransaction::TYPE_PURCHASED:
case PhortuneCartTransaction::TYPE_HOLD:
case PhortuneCartTransaction::TYPE_REVIEW:
case PhortuneCartTransaction::TYPE_CANCEL:
case PhortuneCartTransaction::TYPE_REFUND:
case PhortuneCartTransaction::TYPE_INVOICED:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject(pht('Order %d: %s', $id, $name));
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
if ($this->isInvoice()) {
$issues = $this->getInvoiceIssues();
foreach ($issues as $key => $issue) {
$issues[$key] = ' - '.$issue;
}
$issues = implode("\n", $issues);
$overview = pht(
"Payment for this invoice could not be processed automatically:\n\n".
"%s",
$issues);
$body->addRemarkupSection(null, $overview);
$body->addLinkSection(
pht('PAY NOW'),
PhabricatorEnv::getProductionURI($object->getCheckoutURI()));
}
$items = array();
foreach ($object->getPurchases() as $purchase) {
$name = $purchase->getFullDisplayName();
$price = $purchase->getTotalPriceAsCurrency()->formatForDisplay();
$items[] = "{$name} {$price}";
}
$body->addTextSection(pht('ORDER CONTENTS'), implode("\n", $items));
if ($this->isInvoice()) {
$subscription = id(new PhortuneSubscriptionQuery())
->setViewer($this->requireActor())
->withPHIDs(array($object->getSubscriptionPHID()))
->executeOne();
if ($subscription) {
$body->addLinkSection(
pht('SUBSCRIPTION'),
PhabricatorEnv::getProductionURI($subscription->getURI()));
}
} else {
$body->addLinkSection(
pht('ORDER DETAIL'),
PhabricatorEnv::getProductionURI($object->getDetailURI()));
}
$account_uri = '/phortune/'.$object->getAccount()->getID().'/';
$body->addLinkSection(
pht('ACCOUNT OVERVIEW'),
PhabricatorEnv::getProductionURI($account_uri));
return $body;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
// Reload the cart to pull account information, in case we just created the
// object.
$cart = id(new PhortuneCartQuery())
->setViewer($this->requireActor())
->withPHIDs(array($object->getPHID()))
->executeOne();
foreach ($cart->getAccount()->getMemberPHIDs() as $account_member) {
$phids[] = $account_member;
}
return $phids;
}
protected function getMailCC(PhabricatorLiskDAO $object) {
return array();
}
protected function getMailSubjectPrefix() {
return '[Phortune]';
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhortuneCartReplyHandler())
->setMailReceiver($object);
}
protected function willPublish(PhabricatorLiskDAO $object, array $xactions) {
// We need the purchases in order to build mail.
return id(new PhortuneCartQuery())
->setViewer($this->getActor())
->withIDs(array($object->getID()))
->needPurchases(true)
->executeOne();
}
protected function getCustomWorkerState() {
return array(
'invoiceIssues' => $this->invoiceIssues,
);
}
protected function loadCustomWorkerState(array $state) {
$this->invoiceIssues = idx($state, 'invoiceIssues');
return $this;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$account = $object->getAccount();
$merchant = $object->getMerchant();
$account->writeMerchantEdge($merchant);
return $xactions;
}
protected function newAuxiliaryMail($object, array $xactions) {
$xviewer = PhabricatorUser::getOmnipotentUser();
$account = $object->getAccount();
$addresses = id(new PhortuneAccountEmailQuery())
->setViewer($xviewer)
->withAccountPHIDs(array($account->getPHID()))
->withStatuses(
array(
PhortuneAccountEmailStatus::STATUS_ACTIVE,
))
->execute();
$messages = array();
foreach ($addresses as $address) {
$message = $this->newExternalMail($address, $object, $xactions);
if ($message) {
$messages[] = $message;
}
}
return $messages;
}
private function newExternalMail(
PhortuneAccountEmail $email,
PhortuneCart $cart,
array $xactions) {
$xviewer = PhabricatorUser::getOmnipotentUser();
$account = $cart->getAccount();
$id = $cart->getID();
$name = $cart->getName();
$origin_user = id(new PhabricatorPeopleQuery())
->setViewer($xviewer)
->withPHIDs(array($email->getAuthorPHID()))
->executeOne();
if (!$origin_user) {
return null;
}
if ($this->isInvoice()) {
$subject = pht('[Invoice #%d] %s', $id, $name);
$order_header = pht('INVOICE DETAIL');
} else {
$subject = pht('[Order #%d] %s', $id, $name);
$order_header = pht('ORDER DETAIL');
}
$body = id(new PhabricatorMetaMTAMailBody())
->setViewer($xviewer)
->setContextObject($cart);
$origin_username = $origin_user->getUsername();
$origin_realname = $origin_user->getRealName();
if (strlen($origin_realname)) {
$origin_display = pht('%s (%s)', $origin_username, $origin_realname);
} else {
$origin_display = pht('%s', $origin_username);
}
$body->addRawSection(
pht(
'This email address (%s) was added to a payment account (%s) '.
'by %s.',
$email->getAddress(),
$account->getName(),
$origin_display));
$body->addLinkSection(
$order_header,
PhabricatorEnv::getProductionURI($email->getExternalOrderURI($cart)));
$body->addLinkSection(
pht('FULL ORDER HISTORY'),
PhabricatorEnv::getProductionURI($email->getExternalURI()));
$body->addLinkSection(
pht('UNSUBSCRIBE'),
PhabricatorEnv::getProductionURI($email->getUnsubscribeURI()));
return id(new PhabricatorMetaMTAMail())
->setFrom($this->getActingAsPHID())
->setSubject($subject)
->addRawTos(
array(
$email->getAddress(),
))
->setForceDelivery(true)
->setIsBulk(true)
->setSensitiveContent(true)
->setBody($body->render())
->setHTMLBody($body->renderHTML());
}
}
diff --git a/src/applications/phortune/editor/PhortuneMerchantEditEngine.php b/src/applications/phortune/editor/PhortuneMerchantEditEngine.php
index e09fba99ab..51e93f9c94 100644
--- a/src/applications/phortune/editor/PhortuneMerchantEditEngine.php
+++ b/src/applications/phortune/editor/PhortuneMerchantEditEngine.php
@@ -1,148 +1,148 @@
<?php
final class PhortuneMerchantEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phortune.merchant';
public function getEngineName() {
return pht('Phortune');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Phortune Merchant Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms for Phortune Merchants.');
}
protected function newEditableObject() {
return PhortuneMerchant::initializeNewMerchant($this->getViewer());
}
protected function newObjectQuery() {
return new PhortuneMerchantQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Merchant');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Merchant: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Merchant');
}
protected function getObjectName() {
return pht('Merchant');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('edit/');
}
protected function getObjectViewURI($object) {
return $object->getDetailsURI();
}
public function isEngineConfigurable() {
return false;
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhortuneMerchantCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
if ($this->getIsCreate()) {
$member_phids = array($viewer->getPHID());
} else {
$member_phids = $object->getMemberPHIDs();
}
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Merchant name.'))
->setConduitTypeDescription(pht('New Merchant name.'))
->setIsRequired(true)
->setTransactionType(
PhortuneMerchantNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName()),
id(new PhabricatorUsersEditField())
->setKey('members')
->setAliases(array('memberPHIDs', 'managerPHIDs'))
->setLabel(pht('Managers'))
->setUseEdgeTransactions(true)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhortuneMerchantHasMemberEdgeType::EDGECONST)
->setDescription(pht('Initial merchant managers.'))
->setConduitDescription(pht('Set merchant managers.'))
->setConduitTypeDescription(pht('New list of managers.'))
->setInitialValue($object->getMemberPHIDs())
->setValue($member_phids),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('Merchant description.'))
->setConduitTypeDescription(pht('New merchant description.'))
->setTransactionType(
PhortuneMerchantDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
id(new PhabricatorRemarkupEditField())
->setKey('contactInfo')
->setLabel(pht('Contact Info'))
->setDescription(pht('Merchant contact information.'))
->setConduitTypeDescription(pht('Merchant contact information.'))
->setTransactionType(
PhortuneMerchantContactInfoTransaction::TRANSACTIONTYPE)
->setValue($object->getContactInfo()),
id(new PhabricatorTextEditField())
->setKey('invoiceEmail')
->setLabel(pht('Invoice From Email'))
->setDescription(pht('Email address invoices are sent from.'))
->setConduitTypeDescription(
pht('Email address invoices are sent from.'))
->setTransactionType(
PhortuneMerchantInvoiceEmailTransaction::TRANSACTIONTYPE)
->setValue($object->getInvoiceEmail()),
id(new PhabricatorRemarkupEditField())
->setKey('invoiceFooter')
->setLabel(pht('Invoice Footer'))
->setDescription(pht('Footer on invoice forms.'))
->setConduitTypeDescription(pht('Footer on invoice forms.'))
->setTransactionType(
PhortuneMerchantInvoiceFooterTransaction::TRANSACTIONTYPE)
->setValue($object->getInvoiceFooter()),
);
}
}
diff --git a/src/applications/phortune/editor/PhortuneMerchantEditor.php b/src/applications/phortune/editor/PhortuneMerchantEditor.php
index 79fc7d534e..38a844c3ff 100644
--- a/src/applications/phortune/editor/PhortuneMerchantEditor.php
+++ b/src/applications/phortune/editor/PhortuneMerchantEditor.php
@@ -1,59 +1,59 @@
<?php
final class PhortuneMerchantEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Merchants');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this merchant.', $author);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case PhabricatorTransactions::TYPE_EDGE:
foreach ($xactions as $xaction) {
switch ($xaction->getMetadataValue('edge:type')) {
case PhortuneMerchantHasMemberEdgeType::EDGECONST:
$new = $xaction->getNewValue();
$set = idx($new, '-', array());
$actor_phid = $this->requireActor()->getPHID();
foreach ($set as $phid) {
if ($actor_phid == $phid) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('You can not remove yourself as an merchant manager.'),
$xaction);
$errors[] = $error;
}
}
break;
}
}
break;
}
return $errors;
}
}
diff --git a/src/applications/phortune/editor/PhortunePaymentMethodEditor.php b/src/applications/phortune/editor/PhortunePaymentMethodEditor.php
index 4b6c8cedb3..629958dad1 100644
--- a/src/applications/phortune/editor/PhortunePaymentMethodEditor.php
+++ b/src/applications/phortune/editor/PhortunePaymentMethodEditor.php
@@ -1,18 +1,18 @@
<?php
final class PhortunePaymentMethodEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Payment Methods');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this payment method.', $author);
}
}
diff --git a/src/applications/phortune/editor/PhortunePaymentProviderConfigEditor.php b/src/applications/phortune/editor/PhortunePaymentProviderConfigEditor.php
index 96ac6e830a..84d7cff9ee 100644
--- a/src/applications/phortune/editor/PhortunePaymentProviderConfigEditor.php
+++ b/src/applications/phortune/editor/PhortunePaymentProviderConfigEditor.php
@@ -1,89 +1,89 @@
<?php
final class PhortunePaymentProviderConfigEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Payment Providers');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhortunePaymentProviderConfigTransaction::TYPE_CREATE;
$types[] = PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY;
$types[] = PhortunePaymentProviderConfigTransaction::TYPE_ENABLE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortunePaymentProviderConfigTransaction::TYPE_CREATE:
return null;
case PhortunePaymentProviderConfigTransaction::TYPE_ENABLE:
return (int)$object->getIsEnabled();
case PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY:
$property_key = $xaction->getMetadataValue(
PhortunePaymentProviderConfigTransaction::PROPERTY_KEY);
return $object->getMetadataValue($property_key);
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortunePaymentProviderConfigTransaction::TYPE_CREATE:
case PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY:
return $xaction->getNewValue();
case PhortunePaymentProviderConfigTransaction::TYPE_ENABLE:
return (int)$xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortunePaymentProviderConfigTransaction::TYPE_CREATE:
return;
case PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY:
$property_key = $xaction->getMetadataValue(
PhortunePaymentProviderConfigTransaction::PROPERTY_KEY);
$object->setMetadataValue($property_key, $xaction->getNewValue());
return;
case PhortunePaymentProviderConfigTransaction::TYPE_ENABLE:
return $object->setIsEnabled((int)$xaction->getNewValue());
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortunePaymentProviderConfigTransaction::TYPE_CREATE:
case PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY:
case PhortunePaymentProviderConfigTransaction::TYPE_ENABLE:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
}
diff --git a/src/applications/phortune/editor/PhortuneSubscriptionEditor.php b/src/applications/phortune/editor/PhortuneSubscriptionEditor.php
index a2314f5650..4e9c7dc919 100644
--- a/src/applications/phortune/editor/PhortuneSubscriptionEditor.php
+++ b/src/applications/phortune/editor/PhortuneSubscriptionEditor.php
@@ -1,18 +1,18 @@
<?php
final class PhortuneSubscriptionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phortune Subscriptions');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this subscription.', $author);
}
}
diff --git a/src/applications/phortune/phid/PhortuneAccountEmailPHIDType.php b/src/applications/phortune/phid/PhortuneAccountEmailPHIDType.php
index fccd50cf16..3ae2f295e5 100644
--- a/src/applications/phortune/phid/PhortuneAccountEmailPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneAccountEmailPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhortuneAccountEmailPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AEML';
public function getTypeName() {
return pht('Phortune Account Email');
}
public function newObject() {
return new PhortuneAccountEmail();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneAccountEmailQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$email = $objects[$phid];
$id = $email->getID();
$handle->setName($email->getObjectName());
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneAccountPHIDType.php b/src/applications/phortune/phid/PhortuneAccountPHIDType.php
index 90632a980d..7f38be410c 100644
--- a/src/applications/phortune/phid/PhortuneAccountPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneAccountPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhortuneAccountPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ACNT';
public function getTypeName() {
return pht('Phortune Account');
}
public function newObject() {
return new PhortuneAccount();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneAccountQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$account = $objects[$phid];
$handle
->setName($account->getName())
->setURI($account->getURI());
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneCartPHIDType.php b/src/applications/phortune/phid/PhortuneCartPHIDType.php
index c805a4a921..eceddfe2ad 100644
--- a/src/applications/phortune/phid/PhortuneCartPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneCartPHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhortuneCartPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CART';
public function getTypeName() {
return pht('Phortune Cart');
}
public function newObject() {
return new PhortuneCart();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneCartQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$cart = $objects[$phid];
$id = $cart->getID();
$name = $cart->getName();
$handle->setName($name);
$handle->setURI("/phortune/cart/{$id}/");
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneChargePHIDType.php b/src/applications/phortune/phid/PhortuneChargePHIDType.php
index 013db6ab1c..b41d64b5b6 100644
--- a/src/applications/phortune/phid/PhortuneChargePHIDType.php
+++ b/src/applications/phortune/phid/PhortuneChargePHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhortuneChargePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CHRG';
public function getTypeName() {
return pht('Phortune Charge');
}
public function newObject() {
return new PhortuneCharge();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneChargeQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$charge = $objects[$phid];
$id = $charge->getID();
$handle->setName(pht('Charge %d', $id));
$handle->setURI("/phortune/charge/{$id}/");
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneMerchantPHIDType.php b/src/applications/phortune/phid/PhortuneMerchantPHIDType.php
index 69b93582b3..0f4fe43174 100644
--- a/src/applications/phortune/phid/PhortuneMerchantPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneMerchantPHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhortuneMerchantPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PMRC';
public function getTypeName() {
return pht('Phortune Merchant');
}
public function newObject() {
return new PhortuneMerchant();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneMerchantQuery())
->withPHIDs($phids)
->needProfileImage(true);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$merchant = $objects[$phid];
$handle
->setName($merchant->getName())
->setURI($merchant->getURI())
->setImageURI($merchant->getProfileImageURI());
}
}
}
diff --git a/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php b/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php
index 7de421a7b4..846c3c2cbc 100644
--- a/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php
+++ b/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhortunePaymentMethodPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PAYM';
public function getTypeName() {
return pht('Phortune Payment Method');
}
public function newObject() {
return new PhortunePaymentMethod();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortunePaymentMethodQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$method = $objects[$phid];
$handle
->setName($method->getFullDisplayName())
->setURI($method->getURI());
}
}
}
diff --git a/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php b/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php
index dc96d08648..74b4a05a69 100644
--- a/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php
+++ b/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhortunePaymentProviderPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PHPR';
public function getTypeName() {
return pht('Phortune Payment Provider');
}
public function newObject() {
return new PhortunePaymentProviderConfig();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortunePaymentProviderConfigQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$provider_config = $objects[$phid];
$id = $provider_config->getID();
$handle->setName($provider_config->buildProvider()->getName());
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneProductPHIDType.php b/src/applications/phortune/phid/PhortuneProductPHIDType.php
index 409377186f..3d79471b1f 100644
--- a/src/applications/phortune/phid/PhortuneProductPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneProductPHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhortuneProductPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PDCT';
public function getTypeName() {
return pht('Phortune Product');
}
public function newObject() {
return new PhortuneProduct();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneProductQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$product = $objects[$phid];
$id = $product->getID();
$handle->setName(pht('Product %d', $id));
$handle->setURI("/phortune/product/{$id}/");
}
}
}
diff --git a/src/applications/phortune/phid/PhortunePurchasePHIDType.php b/src/applications/phortune/phid/PhortunePurchasePHIDType.php
index 08f88b1d33..e1faad923b 100644
--- a/src/applications/phortune/phid/PhortunePurchasePHIDType.php
+++ b/src/applications/phortune/phid/PhortunePurchasePHIDType.php
@@ -1,42 +1,42 @@
<?php
final class PhortunePurchasePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PRCH';
public function getTypeName() {
return pht('Phortune Purchase');
}
public function newObject() {
return new PhortunePurchase();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortunePurchaseQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$purchase = $objects[$phid];
$id = $purchase->getID();
$handle->setName($purchase->getFullDisplayName());
$handle->setURI($purchase->getURI());
}
}
}
diff --git a/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php b/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php
index e07dce12f4..caf505fa55 100644
--- a/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php
+++ b/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhortuneSubscriptionPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PSUB';
public function getTypeName() {
return pht('Phortune Subscription');
}
public function newObject() {
return new PhortuneSubscription();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhortuneSubscriptionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$subscription = $objects[$phid];
$handle
->setName($subscription->getSubscriptionName())
->setURI($subscription->getURI());
}
}
}
diff --git a/src/applications/phortune/query/PhortuneAccountEmailQuery.php b/src/applications/phortune/query/PhortuneAccountEmailQuery.php
index 0e0a668b8c..3e2aee1f6a 100644
--- a/src/applications/phortune/query/PhortuneAccountEmailQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountEmailQuery.php
@@ -1,113 +1,113 @@
<?php
final class PhortuneAccountEmailQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $addressKeys;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $phids) {
$this->accountPHIDs = $phids;
return $this;
}
public function withAddressKeys(array $keys) {
$this->addressKeys = $keys;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhortuneAccountEmail();
}
protected function willFilterPage(array $addresses) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($addresses, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($addresses as $key => $address) {
$account = idx($accounts, $address->getAccountPHID());
if (!$account) {
$this->didRejectResult($addresses[$key]);
unset($addresses[$key]);
continue;
}
$address->attachAccount($account);
}
return $addresses;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'address.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'address.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'address.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->addressKeys !== null) {
$where[] = qsprintf(
$conn,
'address.addressKey IN (%Ls)',
$this->addressKeys);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'address.status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function getPrimaryTableAlias() {
return 'address';
}
}
diff --git a/src/applications/phortune/query/PhortuneAccountQuery.php b/src/applications/phortune/query/PhortuneAccountQuery.php
index 43c7c5f976..5defc2d9d6 100644
--- a/src/applications/phortune/query/PhortuneAccountQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountQuery.php
@@ -1,134 +1,134 @@
<?php
final class PhortuneAccountQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
public static function loadAccountsForUser(
PhabricatorUser $user,
PhabricatorContentSource $content_source) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($user)
->withMemberPHIDs(array($user->getPHID()))
->execute();
if (!$accounts) {
$accounts = array(
PhortuneAccount::createNewAccount($user, $content_source),
);
}
$accounts = mpull($accounts, null, 'getPHID');
return $accounts;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMemberPHIDs(array $phids) {
$this->memberPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhortuneAccount();
}
protected function willFilterPage(array $accounts) {
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($accounts, 'getPHID'))
->withEdgeTypes(
array(
PhortuneAccountHasMemberEdgeType::EDGECONST,
PhortuneAccountHasMerchantEdgeType::EDGECONST,
));
$query->execute();
foreach ($accounts as $account) {
$member_phids = $query->getDestinationPHIDs(
array(
$account->getPHID(),
),
array(
PhortuneAccountHasMemberEdgeType::EDGECONST,
));
$member_phids = array_reverse($member_phids);
$account->attachMemberPHIDs($member_phids);
$merchant_phids = $query->getDestinationPHIDs(
array(
$account->getPHID(),
),
array(
PhortuneAccountHasMerchantEdgeType::EDGECONST,
));
$merchant_phids = array_reverse($merchant_phids);
$account->attachMerchantPHIDs($merchant_phids);
}
return $accounts;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'a.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'a.phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn,
'm.dst IN (%Ls)',
$this->memberPHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T m ON a.phid = m.src AND m.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhortuneAccountHasMemberEdgeType::EDGECONST);
}
return $joins;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function getPrimaryTableAlias() {
return 'a';
}
}
diff --git a/src/applications/phortune/query/PhortuneCartQuery.php b/src/applications/phortune/query/PhortuneCartQuery.php
index 0b3325b932..e54578731f 100644
--- a/src/applications/phortune/query/PhortuneCartQuery.php
+++ b/src/applications/phortune/query/PhortuneCartQuery.php
@@ -1,223 +1,223 @@
<?php
final class PhortuneCartQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $subscriptionPHIDs;
private $statuses;
private $invoices;
private $needPurchases;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withMerchantPHIDs(array $merchant_phids) {
$this->merchantPHIDs = $merchant_phids;
return $this;
}
public function withSubscriptionPHIDs(array $subscription_phids) {
$this->subscriptionPHIDs = $subscription_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
/**
* Include or exclude carts which represent invoices with payments due.
*
* @param bool `true` to select invoices; `false` to exclude invoices.
* @return this
*/
public function withInvoices($invoices) {
$this->invoices = $invoices;
return $this;
}
public function needPurchases($need_purchases) {
$this->needPurchases = $need_purchases;
return $this;
}
protected function loadPage() {
$table = new PhortuneCart();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT cart.* FROM %T cart %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $carts) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($carts, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($carts as $key => $cart) {
$account = idx($accounts, $cart->getAccountPHID());
if (!$account) {
unset($carts[$key]);
continue;
}
$cart->attachAccount($account);
}
if (!$carts) {
return array();
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($carts, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($carts as $key => $cart) {
$merchant = idx($merchants, $cart->getMerchantPHID());
if (!$merchant) {
unset($carts[$key]);
continue;
}
$cart->attachMerchant($merchant);
}
if (!$carts) {
return array();
}
$implementations = array();
$cart_map = mgroup($carts, 'getCartClass');
foreach ($cart_map as $class => $class_carts) {
$implementations += newv($class, array())->loadImplementationsForCarts(
$this->getViewer(),
$class_carts);
}
foreach ($carts as $key => $cart) {
$implementation = idx($implementations, $key);
if (!$implementation) {
unset($carts[$key]);
continue;
}
$cart->attachImplementation($implementation);
}
return $carts;
}
protected function didFilterPage(array $carts) {
if ($this->needPurchases) {
$purchases = id(new PhortunePurchaseQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withCartPHIDs(mpull($carts, 'getPHID'))
->execute();
$purchases = mgroup($purchases, 'getCartPHID');
foreach ($carts as $cart) {
$cart->attachPurchases(idx($purchases, $cart->getPHID(), array()));
}
}
return $carts;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'cart.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'cart.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->subscriptionPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.subscriptionPHID IN (%Ls)',
$this->subscriptionPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'cart.status IN (%Ls)',
$this->statuses);
}
if ($this->invoices !== null) {
if ($this->invoices) {
$where[] = qsprintf(
$conn,
'cart.status = %s AND cart.isInvoice = 1',
PhortuneCart::STATUS_READY);
} else {
$where[] = qsprintf(
$conn,
'cart.status != %s OR cart.isInvoice = 0',
PhortuneCart::STATUS_READY);
}
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortuneCartSearchEngine.php b/src/applications/phortune/query/PhortuneCartSearchEngine.php
index a4a0f2848d..b017591fb8 100644
--- a/src/applications/phortune/query/PhortuneCartSearchEngine.php
+++ b/src/applications/phortune/query/PhortuneCartSearchEngine.php
@@ -1,218 +1,218 @@
<?php
final class PhortuneCartSearchEngine
extends PhabricatorApplicationSearchEngine {
private $merchant;
private $account;
private $subscription;
public function canUseInPanelContext() {
// These only make sense in an account or merchant context.
return false;
}
public function setAccount(PhortuneAccount $account) {
$this->account = $account;
return $this;
}
public function getAccount() {
return $this->account;
}
public function setMerchant(PhortuneMerchant $merchant) {
$this->merchant = $merchant;
return $this;
}
public function getMerchant() {
return $this->merchant;
}
public function setSubscription(PhortuneSubscription $subscription) {
$this->subscription = $subscription;
return $this;
}
public function getSubscription() {
return $this->subscription;
}
public function getResultTypeDescription() {
return pht('Phortune Orders');
}
public function getApplicationClassName() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhortuneCartQuery())
->needPurchases(true);
$viewer = $this->requireViewer();
$merchant = $this->getMerchant();
$account = $this->getAccount();
if ($merchant) {
$query->withMerchantPHIDs(array($merchant->getPHID()));
} else if ($account) {
$query->withAccountPHIDs(array($account->getPHID()));
} else {
$accounts = id(new PhortuneAccountQuery())
->withMemberPHIDs(array($viewer->getPHID()))
->execute();
if ($accounts) {
$query->withAccountPHIDs(mpull($accounts, 'getPHID'));
} else {
throw new Exception(pht('You have no accounts!'));
}
}
$subscription = $this->getSubscription();
if ($subscription) {
$query->withSubscriptionPHIDs(array($subscription->getPHID()));
}
if ($saved->getParameter('invoices')) {
$query->withInvoices(true);
} else {
$query->withStatuses(
array(
PhortuneCart::STATUS_PURCHASING,
PhortuneCart::STATUS_CHARGED,
PhortuneCart::STATUS_HOLD,
PhortuneCart::STATUS_REVIEW,
PhortuneCart::STATUS_PURCHASED,
));
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {}
protected function getURI($path) {
$merchant = $this->getMerchant();
$account = $this->getAccount();
if ($merchant) {
return $merchant->getOrderListURI($path);
} else if ($account) {
return $account->getOrderListURI($path);
} else {
return '/phortune/order/'.$path;
}
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('Order History'),
'invoices' => pht('Unpaid Invoices'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'invoices':
return $query->setParameter('invoices', true);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $carts,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($carts as $cart) {
$phids[] = $cart->getPHID();
$phids[] = $cart->getMerchantPHID();
$phids[] = $cart->getAuthorPHID();
}
return $phids;
}
protected function renderResultList(
array $carts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($carts, 'PhortuneCart');
$viewer = $this->requireViewer();
$rows = array();
foreach ($carts as $cart) {
$merchant = $cart->getMerchant();
if ($this->getMerchant()) {
$href = $this->getApplicationURI(
'merchant/'.$merchant->getID().'/cart/'.$cart->getID().'/');
} else {
$href = $cart->getDetailURI();
}
$rows[] = array(
$cart->getID(),
$handles[$cart->getPHID()]->renderLink(),
$handles[$merchant->getPHID()]->renderLink(),
$handles[$cart->getAuthorPHID()]->renderLink(),
$cart->getTotalPriceAsCurrency()->formatForDisplay(),
PhortuneCart::getNameForStatus($cart->getStatus()),
phabricator_datetime($cart->getDateModified(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setNoDataString(pht('No orders match the query.'))
->setHeaders(
array(
pht('ID'),
pht('Order'),
pht('Merchant'),
pht('Authorized By'),
pht('Amount'),
pht('Status'),
pht('Updated'),
))
->setColumnClasses(
array(
'',
'pri',
'',
'',
'wide right',
'',
'right',
));
$merchant = $this->getMerchant();
if ($merchant) {
$notice = pht('Orders for %s', $merchant->getName());
} else {
$notice = pht('Your Orders');
}
$table->setNotice($notice);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
return $result;
}
}
diff --git a/src/applications/phortune/query/PhortuneChargeQuery.php b/src/applications/phortune/query/PhortuneChargeQuery.php
index a7eda9d6a6..a0f6026fa6 100644
--- a/src/applications/phortune/query/PhortuneChargeQuery.php
+++ b/src/applications/phortune/query/PhortuneChargeQuery.php
@@ -1,144 +1,144 @@
<?php
final class PhortuneChargeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $cartPHIDs;
private $statuses;
private $needCarts;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withCartPHIDs(array $cart_phids) {
$this->cartPHIDs = $cart_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needCarts($need_carts) {
$this->needCarts = $need_carts;
return $this;
}
protected function loadPage() {
$table = new PhortuneCharge();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT charge.* FROM %T charge %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $charges) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($charges, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($charges as $key => $charge) {
$account = idx($accounts, $charge->getAccountPHID());
if (!$account) {
unset($charges[$key]);
continue;
}
$charge->attachAccount($account);
}
return $charges;
}
protected function didFilterPage(array $charges) {
if ($this->needCarts) {
$carts = id(new PhortuneCartQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($charges, 'getCartPHID'))
->execute();
$carts = mpull($carts, null, 'getPHID');
foreach ($charges as $charge) {
$cart = idx($carts, $charge->getCartPHID());
$charge->attachCart($cart);
}
}
return $charges;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'charge.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'charge.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'charge.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->cartPHIDs !== null) {
$where[] = qsprintf(
$conn,
'charge.cartPHID IN (%Ls)',
$this->cartPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'charge.status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortuneChargeSearchEngine.php b/src/applications/phortune/query/PhortuneChargeSearchEngine.php
index e1fb5a47ba..568d60fc1a 100644
--- a/src/applications/phortune/query/PhortuneChargeSearchEngine.php
+++ b/src/applications/phortune/query/PhortuneChargeSearchEngine.php
@@ -1,110 +1,110 @@
<?php
final class PhortuneChargeSearchEngine
extends PhabricatorApplicationSearchEngine {
private $account;
public function canUseInPanelContext() {
// These only make sense in an account context.
return false;
}
public function setAccount(PhortuneAccount $account) {
$this->account = $account;
return $this;
}
public function getAccount() {
return $this->account;
}
public function getResultTypeDescription() {
return pht('Phortune Charges');
}
public function getApplicationClassName() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhortuneChargeQuery());
$viewer = $this->requireViewer();
$account = $this->getAccount();
if ($account) {
$query->withAccountPHIDs(array($account->getPHID()));
} else {
$accounts = id(new PhortuneAccountQuery())
->withMemberPHIDs(array($viewer->getPHID()))
->execute();
if ($accounts) {
$query->withAccountPHIDs(mpull($accounts, 'getPHID'));
} else {
throw new Exception(pht('You have no accounts!'));
}
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {}
protected function getURI($path) {
$account = $this->getAccount();
if ($account) {
return $account->getChargeListURI($path);
} else {
return '/phortune/charge/'.$path;
}
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Charges'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $charges,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($charges, 'PhortuneCharge');
$viewer = $this->requireViewer();
$table = id(new PhortuneChargeTableView())
->setUser($viewer)
->setCharges($charges);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
return $result;
}
}
diff --git a/src/applications/phortune/query/PhortuneMerchantQuery.php b/src/applications/phortune/query/PhortuneMerchantQuery.php
index 2c9aefc74d..19b32d1338 100644
--- a/src/applications/phortune/query/PhortuneMerchantQuery.php
+++ b/src/applications/phortune/query/PhortuneMerchantQuery.php
@@ -1,189 +1,189 @@
<?php
final class PhortuneMerchantQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
private $needProfileImage;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMemberPHIDs(array $member_phids) {
$this->memberPHIDs = $member_phids;
return $this;
}
public function needProfileImage($need) {
$this->needProfileImage = $need;
return $this;
}
public function newResultObject() {
return new PhortuneMerchant();
}
protected function willFilterPage(array $merchants) {
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($merchants, 'getPHID'))
->withEdgeTypes(array(PhortuneMerchantHasMemberEdgeType::EDGECONST));
$query->execute();
foreach ($merchants as $merchant) {
$member_phids = $query->getDestinationPHIDs(array($merchant->getPHID()));
$member_phids = array_reverse($member_phids);
$merchant->attachMemberPHIDs($member_phids);
}
if ($this->needProfileImage) {
$default = null;
$file_phids = mpull($merchants, 'getProfileImagePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($merchants as $merchant) {
$file = idx($files, $merchant->getProfileImagePHID());
if (!$file) {
if (!$default) {
$default = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'merchant.png');
}
$file = $default;
}
$merchant->attachProfileImageFile($file);
}
}
return $merchants;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'merchant.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'merchant.phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn,
'e.dst IN (%Ls)',
$this->memberPHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T e ON merchant.phid = e.src AND e.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhortuneMerchantHasMemberEdgeType::EDGECONST);
}
return $joins;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
protected function getPrimaryTableAlias() {
return 'merchant';
}
public static function canViewersEditMerchants(
array $viewer_phids,
array $merchant_phids) {
// See T13366 for some discussion. This is an unusual caching construct to
// make policy filtering of Accounts easier.
foreach ($viewer_phids as $key => $viewer_phid) {
if (!$viewer_phid) {
unset($viewer_phids[$key]);
}
}
if (!$viewer_phids) {
return array();
}
$cache_key = 'phortune.merchant.can-edit';
$cache = PhabricatorCaches::getRequestCache();
$cache_data = $cache->getKey($cache_key);
if (!$cache_data) {
$cache_data = array();
}
$load_phids = array();
foreach ($viewer_phids as $viewer_phid) {
if (!isset($cache_data[$viewer_phid])) {
$load_phids[] = $viewer_phid;
}
}
$did_write = false;
foreach ($load_phids as $load_phid) {
$merchants = id(new self())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withMemberPHIDs(array($load_phid))
->execute();
foreach ($merchants as $merchant) {
$cache_data[$load_phid][$merchant->getPHID()] = true;
$did_write = true;
}
}
if ($did_write) {
$cache->setKey($cache_key, $cache_data);
}
$results = array();
foreach ($viewer_phids as $viewer_phid) {
foreach ($merchant_phids as $merchant_phid) {
if (!isset($cache_data[$viewer_phid][$merchant_phid])) {
continue;
}
$results[$viewer_phid][$merchant_phid] = true;
}
}
return $results;
}
}
diff --git a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php
index a818f37d28..0688fa5344 100644
--- a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php
+++ b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php
@@ -1,89 +1,89 @@
<?php
final class PhortuneMerchantSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phortune Merchants');
}
public function getApplicationClassName() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhortuneMerchantQuery())
->needProfileImage(true);
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {}
protected function getURI($path) {
return '/phortune/merchant/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Merchants'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $merchants,
PhabricatorSavedQuery $query) {
return array();
}
protected function renderResultList(
array $merchants,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($merchants, 'PhortuneMerchant');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($merchants as $merchant) {
$item = id(new PHUIObjectItemView())
->setSubhead(pht('Merchant %d', $merchant->getID()))
->setHeader($merchant->getName())
->setHref('/phortune/merchant/'.$merchant->getID().'/')
->setObject($merchant)
->setImageURI($merchant->getProfileImageURI());
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No merchants found.'));
return $result;
}
}
diff --git a/src/applications/phortune/query/PhortunePaymentMethodQuery.php b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
index b95881d3a7..aeea908506 100644
--- a/src/applications/phortune/query/PhortunePaymentMethodQuery.php
+++ b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
@@ -1,146 +1,146 @@
<?php
final class PhortunePaymentMethodQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $phids) {
$this->accountPHIDs = $phids;
return $this;
}
public function withMerchantPHIDs(array $phids) {
$this->merchantPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhortunePaymentMethod();
}
protected function willFilterPage(array $methods) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($methods as $key => $method) {
$account = idx($accounts, $method->getAccountPHID());
if (!$account) {
unset($methods[$key]);
$this->didRejectResult($method);
continue;
}
$method->attachAccount($account);
}
if (!$methods) {
return $methods;
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($methods as $key => $method) {
$merchant = idx($merchants, $method->getMerchantPHID());
if (!$merchant) {
unset($methods[$key]);
$this->didRejectResult($method);
continue;
}
$method->attachMerchant($merchant);
}
if (!$methods) {
return $methods;
}
$provider_configs = id(new PhortunePaymentProviderConfigQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getProviderPHID'))
->execute();
$provider_configs = mpull($provider_configs, null, 'getPHID');
foreach ($methods as $key => $method) {
$provider_config = idx($provider_configs, $method->getProviderPHID());
if (!$provider_config) {
unset($methods[$key]);
$this->didRejectResult($method);
continue;
}
$method->attachProviderConfig($provider_config);
}
return $methods;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php b/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
index a850acec28..eb478a2997 100644
--- a/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
+++ b/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhortunePaymentProviderConfigQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $merchantPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMerchantPHIDs(array $phids) {
$this->merchantPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhortunePaymentProviderConfig();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $provider_configs) {
$merchant_phids = mpull($provider_configs, 'getMerchantPHID');
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($merchant_phids)
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($provider_configs as $key => $config) {
$merchant = idx($merchants, $config->getMerchantPHID());
if (!$merchant) {
$this->didRejectResult($config);
unset($provider_configs[$key]);
continue;
}
$config->attachMerchant($merchant);
}
return $provider_configs;
}
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->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortuneProductQuery.php b/src/applications/phortune/query/PhortuneProductQuery.php
index 30701d4e7b..d479c37843 100644
--- a/src/applications/phortune/query/PhortuneProductQuery.php
+++ b/src/applications/phortune/query/PhortuneProductQuery.php
@@ -1,120 +1,120 @@
<?php
final class PhortuneProductQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $refMap;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withClassAndRef($class, $ref) {
$this->refMap = array($class => array($ref));
return $this;
}
protected function loadPage() {
$table = new PhortuneProduct();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
$page = $table->loadAllFromArray($rows);
// NOTE: We're loading product implementations here, but also creating any
// products which do not yet exist.
$class_map = mgroup($page, 'getProductClass');
if ($this->refMap) {
$class_map += array_fill_keys(array_keys($this->refMap), array());
}
foreach ($class_map as $class => $products) {
$refs = mpull($products, null, 'getProductRef');
if (isset($this->refMap[$class])) {
$refs += array_fill_keys($this->refMap[$class], null);
}
$implementations = newv($class, array())->loadImplementationsForRefs(
$this->getViewer(),
array_keys($refs));
$implementations = mpull($implementations, null, 'getRef');
foreach ($implementations as $ref => $implementation) {
$product = idx($refs, $ref);
if ($product === null) {
// If this product does not exist yet, create it and add it to the
// result page.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$product = PhortuneProduct::initializeNewProduct()
->setProductClass($class)
->setProductRef($ref)
->save();
unset($unguarded);
$page[] = $product;
}
$product->attachImplementation($implementation);
}
}
return $page;
}
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->refMap !== null) {
$sql = array();
foreach ($this->refMap as $class => $refs) {
foreach ($refs as $ref) {
$sql[] = qsprintf(
$conn,
'(productClassKey = %s AND productRefKey = %s)',
PhabricatorHash::digestForIndex($class),
PhabricatorHash::digestForIndex($ref));
}
}
$where[] = qsprintf($conn, '%LO', $sql);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortunePurchaseQuery.php b/src/applications/phortune/query/PhortunePurchaseQuery.php
index 275537c351..7ed5d1c9a6 100644
--- a/src/applications/phortune/query/PhortunePurchaseQuery.php
+++ b/src/applications/phortune/query/PhortunePurchaseQuery.php
@@ -1,110 +1,110 @@
<?php
final class PhortunePurchaseQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $cartPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCartPHIDs(array $cart_phids) {
$this->cartPHIDs = $cart_phids;
return $this;
}
protected function loadPage() {
$table = new PhortunePurchase();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT purchase.* FROM %T purchase %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $purchases) {
$carts = id(new PhortuneCartQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($purchases, 'getCartPHID'))
->execute();
$carts = mpull($carts, null, 'getPHID');
foreach ($purchases as $key => $purchase) {
$cart = idx($carts, $purchase->getCartPHID());
if (!$cart) {
unset($purchases[$key]);
continue;
}
$purchase->attachCart($cart);
}
$products = id(new PhortuneProductQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($purchases, 'getProductPHID'))
->execute();
$products = mpull($products, null, 'getPHID');
foreach ($purchases as $key => $purchase) {
$product = idx($products, $purchase->getProductPHID());
if (!$product) {
unset($purchases[$key]);
continue;
}
$purchase->attachProduct($product);
}
return $purchases;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'purchase.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'purchase.phid IN (%Ls)',
$this->phids);
}
if ($this->cartPHIDs !== null) {
$where[] = qsprintf(
$conn,
'purchase.cartPHID IN (%Ls)',
$this->cartPHIDs);
}
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortuneSubscriptionQuery.php b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
index 5622578738..c848f74333 100644
--- a/src/applications/phortune/query/PhortuneSubscriptionQuery.php
+++ b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
@@ -1,200 +1,200 @@
<?php
final class PhortuneSubscriptionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $statuses;
private $paymentMethodPHIDs;
private $needTriggers;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withMerchantPHIDs(array $merchant_phids) {
$this->merchantPHIDs = $merchant_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withPaymentMethodPHIDs(array $method_phids) {
$this->paymentMethodPHIDs = $method_phids;
return $this;
}
public function needTriggers($need_triggers) {
$this->needTriggers = $need_triggers;
return $this;
}
public function newResultObject() {
return new PhortuneSubscription();
}
protected function willFilterPage(array $subscriptions) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($subscriptions, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$account = idx($accounts, $subscription->getAccountPHID());
if (!$account) {
unset($subscriptions[$key]);
$this->didRejectResult($subscription);
continue;
}
$subscription->attachAccount($account);
}
if (!$subscriptions) {
return $subscriptions;
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($subscriptions, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$merchant = idx($merchants, $subscription->getMerchantPHID());
if (!$merchant) {
unset($subscriptions[$key]);
$this->didRejectResult($subscription);
continue;
}
$subscription->attachMerchant($merchant);
}
if (!$subscriptions) {
return $subscriptions;
}
$implementations = array();
$subscription_map = mgroup($subscriptions, 'getSubscriptionClass');
foreach ($subscription_map as $class => $class_subscriptions) {
$sub = newv($class, array());
$impl_objects = $sub->loadImplementationsForRefs(
$this->getViewer(),
mpull($class_subscriptions, 'getSubscriptionRef'));
$implementations += mpull($impl_objects, null, 'getRef');
}
foreach ($subscriptions as $key => $subscription) {
$ref = $subscription->getSubscriptionRef();
$implementation = idx($implementations, $ref);
if (!$implementation) {
unset($subscriptions[$key]);
$this->didRejectResult($subscription);
continue;
}
$subscription->attachImplementation($implementation);
}
if (!$subscriptions) {
return $subscriptions;
}
if ($this->needTriggers) {
$trigger_phids = mpull($subscriptions, 'getTriggerPHID');
$triggers = id(new PhabricatorWorkerTriggerQuery())
->setViewer($this->getViewer())
->withPHIDs($trigger_phids)
->needEvents(true)
->execute();
$triggers = mpull($triggers, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$trigger = idx($triggers, $subscription->getTriggerPHID());
if (!$trigger) {
unset($subscriptions[$key]);
$this->didRejectResult($subscription);
continue;
}
$subscription->attachTrigger($trigger);
}
}
return $subscriptions;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'subscription.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'subscription.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'subscription.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'subscription.merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'subscription.status IN (%Ls)',
$this->statuses);
}
if ($this->paymentMethodPHIDs !== null) {
$where[] = qsprintf(
$conn,
'subscription.defaultPaymentMethodPHID IN (%Ls)',
$this->paymentMethodPHIDs);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'subscription';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
}
diff --git a/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php b/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php
index 0d2e720aa7..9da6f34c72 100644
--- a/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php
+++ b/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php
@@ -1,155 +1,155 @@
<?php
final class PhortuneSubscriptionSearchEngine
extends PhabricatorApplicationSearchEngine {
private $merchant;
private $account;
public function canUseInPanelContext() {
// These only make sense in an account or merchant context.
return false;
}
public function setAccount(PhortuneAccount $account) {
$this->account = $account;
return $this;
}
public function getAccount() {
return $this->account;
}
public function setMerchant(PhortuneMerchant $merchant) {
$this->merchant = $merchant;
return $this;
}
public function getMerchant() {
return $this->merchant;
}
public function getResultTypeDescription() {
return pht('Phortune Subscriptions');
}
public function getApplicationClassName() {
- return 'PhabricatorPhortuneApplication';
+ return PhabricatorPhortuneApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhortuneSubscriptionQuery());
$viewer = $this->requireViewer();
$merchant = $this->getMerchant();
$account = $this->getAccount();
if ($merchant) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$merchant,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
throw new Exception(
pht(
'You can not query subscriptions for a merchant you do not '.
'control.'));
}
$query->withMerchantPHIDs(array($merchant->getPHID()));
} else if ($account) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$account,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
throw new Exception(
pht(
'You can not query subscriptions for an account you are not '.
'a member of.'));
}
$query->withAccountPHIDs(array($account->getPHID()));
} else {
$accounts = id(new PhortuneAccountQuery())
->withMemberPHIDs(array($viewer->getPHID()))
->execute();
if ($accounts) {
$query->withAccountPHIDs(mpull($accounts, 'getPHID'));
} else {
throw new Exception(pht('You have no accounts!'));
}
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {}
protected function getURI($path) {
$merchant = $this->getMerchant();
$account = $this->getAccount();
if ($merchant) {
return $merchant->getSubscriptionListURI($path);
} else if ($account) {
return $account->getSubscriptionListURI($path);
} else {
return '/phortune/subscription/'.$path;
}
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Subscriptions'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $subscriptions,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($subscriptions, 'PhortuneSubscription');
$viewer = $this->requireViewer();
$table = id(new PhortuneSubscriptionTableView())
->setUser($viewer)
->setSubscriptions($subscriptions);
$merchant = $this->getMerchant();
if ($merchant) {
$header = pht('Subscriptions for %s', $merchant->getName());
$table->setIsMerchantView(true);
} else {
$header = pht('Your Subscriptions');
}
$table->setNotice($header);
$result = new PhabricatorApplicationSearchResultView();
$result->setTable($table);
return $result;
}
}
diff --git a/src/applications/phrequent/query/PhrequentSearchEngine.php b/src/applications/phrequent/query/PhrequentSearchEngine.php
index d137c40b64..2cf1bb7d4c 100644
--- a/src/applications/phrequent/query/PhrequentSearchEngine.php
+++ b/src/applications/phrequent/query/PhrequentSearchEngine.php
@@ -1,198 +1,198 @@
<?php
final class PhrequentSearchEngine extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phrequent Time');
}
public function getApplicationClassName() {
- return 'PhabricatorPhrequentApplication';
+ return PhabricatorPhrequentApplication::class;
}
public function getPageSize(PhabricatorSavedQuery $saved) {
return $saved->getParameter('limit', 1000);
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'userPHIDs',
$this->readUsersFromRequest($request, 'users'));
$saved->setParameter('ended', $request->getStr('ended'));
$saved->setParameter('order', $request->getStr('order'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhrequentUserTimeQuery())
->needPreemptingEvents(true);
$user_phids = $saved->getParameter('userPHIDs');
if ($user_phids) {
$query->withUserPHIDs($user_phids);
}
$ended = $saved->getParameter('ended');
if ($ended != null) {
$query->withEnded($ended);
}
$order = $saved->getParameter('order');
if ($order != null) {
$query->setOrder($order);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$user_phids = $saved_query->getParameter('userPHIDs', array());
$ended = $saved_query->getParameter(
'ended', PhrequentUserTimeQuery::ENDED_ALL);
$order = $saved_query->getParameter(
'order', PhrequentUserTimeQuery::ORDER_ENDED_DESC);
$form
->appendControl(
id(new AphrontFormTokenizerControl())
->setDatasource(new PhabricatorPeopleDatasource())
->setName('users')
->setLabel(pht('Users'))
->setValue($user_phids))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Ended'))
->setName('ended')
->setValue($ended)
->setOptions(PhrequentUserTimeQuery::getEndedSearchOptions()))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Order'))
->setName('order')
->setValue($order)
->setOptions(PhrequentUserTimeQuery::getOrderSearchOptions()));
}
protected function getURI($path) {
return '/phrequent/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'tracking' => pht('Currently Tracking'),
'all' => pht('All Tracked'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query
->setParameter('order', PhrequentUserTimeQuery::ORDER_ENDED_DESC);
case 'tracking':
return $query
->setParameter('ended', PhrequentUserTimeQuery::ENDED_NO)
->setParameter('order', PhrequentUserTimeQuery::ORDER_ENDED_DESC);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $usertimes,
PhabricatorSavedQuery $query) {
return array_mergev(
array(
mpull($usertimes, 'getUserPHID'),
mpull($usertimes, 'getObjectPHID'),
));
}
protected function renderResultList(
array $usertimes,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($usertimes, 'PhrequentUserTime');
$viewer = $this->requireViewer();
$view = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($usertimes as $usertime) {
$item = new PHUIObjectItemView();
if ($usertime->getObjectPHID() === null) {
$item->setHeader($usertime->getNote());
} else {
$obj = $handles[$usertime->getObjectPHID()];
$item->setHeader($obj->getLinkName());
$item->setHref($obj->getURI());
}
$item->setObject($usertime);
$item->addByline(
pht(
'Tracked: %s',
$handles[$usertime->getUserPHID()]->renderLink()));
$started_date = phabricator_date($usertime->getDateStarted(), $viewer);
$item->addIcon('none', $started_date);
$block = new PhrequentTimeBlock(array($usertime));
$time_spent = $block->getTimeSpentOnObject(
$usertime->getObjectPHID(),
PhabricatorTime::getNow());
$time_spent = $time_spent == 0 ? 'none' :
phutil_format_relative_time_detailed($time_spent);
if ($usertime->getDateEnded() !== null) {
$item->addAttribute(
pht(
'Tracked %s',
$time_spent));
$item->addAttribute(
pht(
'Ended on %s',
phabricator_datetime($usertime->getDateEnded(), $viewer)));
} else {
$item->addAttribute(
pht(
'Tracked %s so far',
$time_spent));
if ($usertime->getObjectPHID() !== null &&
$usertime->getUserPHID() === $viewer->getPHID()) {
$item->addAction(
id(new PHUIListItemView())
->setIcon('fa-stop')
->addSigil('phrequent-stop-tracking')
->setWorkflow(true)
->setRenderNameAsTooltip(true)
->setName(pht('Stop'))
->setHref(
'/phrequent/track/stop/'.
$usertime->getObjectPHID().'/'));
}
$item->setStatusIcon('fa-clock-o green');
}
$view->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($view);
return $result;
}
}
diff --git a/src/applications/phrequent/query/PhrequentUserTimeQuery.php b/src/applications/phrequent/query/PhrequentUserTimeQuery.php
index 6400771a00..7bbd267c00 100644
--- a/src/applications/phrequent/query/PhrequentUserTimeQuery.php
+++ b/src/applications/phrequent/query/PhrequentUserTimeQuery.php
@@ -1,332 +1,332 @@
<?php
final class PhrequentUserTimeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const ORDER_ID_ASC = 0;
const ORDER_ID_DESC = 1;
const ORDER_STARTED_ASC = 2;
const ORDER_STARTED_DESC = 3;
const ORDER_ENDED_ASC = 4;
const ORDER_ENDED_DESC = 5;
const ENDED_YES = 0;
const ENDED_NO = 1;
const ENDED_ALL = 2;
private $ids;
private $userPHIDs;
private $objectPHIDs;
private $ended = self::ENDED_ALL;
private $needPreemptingEvents;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withEnded($ended) {
$this->ended = $ended;
return $this;
}
public function setOrder($order) {
switch ($order) {
case self::ORDER_ID_ASC:
$this->setOrderVector(array('-id'));
break;
case self::ORDER_ID_DESC:
$this->setOrderVector(array('id'));
break;
case self::ORDER_STARTED_ASC:
$this->setOrderVector(array('-start', '-id'));
break;
case self::ORDER_STARTED_DESC:
$this->setOrderVector(array('start', 'id'));
break;
case self::ORDER_ENDED_ASC:
$this->setOrderVector(array('-end', '-id'));
break;
case self::ORDER_ENDED_DESC:
$this->setOrderVector(array('end', 'id'));
break;
default:
throw new Exception(pht('Unknown order "%s".', $order));
}
return $this;
}
public function needPreemptingEvents($need_events) {
$this->needPreemptingEvents = $need_events;
return $this;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
switch ($this->ended) {
case self::ENDED_ALL:
break;
case self::ENDED_YES:
$where[] = qsprintf(
$conn,
'dateEnded IS NOT NULL');
break;
case self::ENDED_NO:
$where[] = qsprintf(
$conn,
'dateEnded IS NULL');
break;
default:
throw new Exception(pht("Unknown ended '%s'!", $this->ended));
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'start' => array(
'column' => 'dateStarted',
'type' => 'int',
),
'end' => array(
'column' => 'dateEnded',
'type' => 'int',
'null' => 'head',
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'start' => (int)$object->getDateStarted(),
'end' => (int)$object->getDateEnded(),
);
}
protected function loadPage() {
$usertime = new PhrequentUserTime();
$conn = $usertime->establishConnection('r');
$data = queryfx_all(
$conn,
'SELECT usertime.* FROM %T usertime %Q %Q %Q',
$usertime->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $usertime->loadAllFromArray($data);
}
protected function didFilterPage(array $page) {
if ($this->needPreemptingEvents) {
$usertime = new PhrequentUserTime();
$conn_r = $usertime->establishConnection('r');
$preempt = array();
foreach ($page as $event) {
$preempt[] = qsprintf(
$conn_r,
'(userPHID = %s AND
(dateStarted BETWEEN %d AND %d) AND
(dateEnded IS NULL OR dateEnded > %d))',
$event->getUserPHID(),
$event->getDateStarted(),
nonempty($event->getDateEnded(), PhabricatorTime::getNow()),
$event->getDateStarted());
}
$preempting_events = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE %LO ORDER BY dateStarted ASC, id ASC',
$usertime->getTableName(),
$preempt);
$preempting_events = $usertime->loadAllFromArray($preempting_events);
$preempting_events = mgroup($preempting_events, 'getUserPHID');
foreach ($page as $event) {
$e_start = $event->getDateStarted();
$e_end = $event->getDateEnded();
$select = array();
$user_events = idx($preempting_events, $event->getUserPHID(), array());
foreach ($user_events as $u_event) {
if ($u_event->getID() == $event->getID()) {
// Don't allow an event to preempt itself.
continue;
}
$u_start = $u_event->getDateStarted();
$u_end = $u_event->getDateEnded();
if ($u_start < $e_start) {
// This event started before our event started, so it's not
// preempting us.
continue;
}
if ($u_start == $e_start) {
if ($u_event->getID() < $event->getID()) {
// This event started at the same time as our event started,
// but has a lower ID, so it's not preempting us.
continue;
}
}
if (($e_end !== null) && ($u_start > $e_end)) {
// Our event has ended, and this event started after it ended.
continue;
}
if (($u_end !== null) && ($u_end < $e_start)) {
// This event ended before our event began.
continue;
}
$select[] = $u_event;
}
$event->attachPreemptingEvents($select);
}
}
return $page;
}
/* -( Helper Functions ) --------------------------------------------------- */
public static function getEndedSearchOptions() {
return array(
self::ENDED_ALL => pht('All'),
self::ENDED_NO => pht('No'),
self::ENDED_YES => pht('Yes'),
);
}
public static function getOrderSearchOptions() {
return array(
self::ORDER_STARTED_ASC => pht('by furthest start date'),
self::ORDER_STARTED_DESC => pht('by nearest start date'),
self::ORDER_ENDED_ASC => pht('by furthest end date'),
self::ORDER_ENDED_DESC => pht('by nearest end date'),
);
}
public static function getUserTotalObjectsTracked(
PhabricatorUser $user,
$limit = PHP_INT_MAX) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
$count = queryfx_one(
$conn,
'SELECT COUNT(usertime.id) N FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.dateEnded IS NULL '.
'LIMIT %d',
$usertime_dao->getTableName(),
$user->getPHID(),
$limit);
return $count['N'];
}
public static function isUserTrackingObject(
PhabricatorUser $user,
$phid) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
$count = queryfx_one(
$conn,
'SELECT COUNT(usertime.id) N FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
return $count['N'] > 0;
}
public static function getUserTimeSpentOnObject(
PhabricatorUser $user,
$phid) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
// First calculate all the time spent where the
// usertime blocks have ended.
$sum_ended = queryfx_one(
$conn,
'SELECT SUM(usertime.dateEnded - usertime.dateStarted) N '.
'FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NOT NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
// Now calculate the time spent where the usertime
// blocks have not yet ended.
$sum_not_ended = queryfx_one(
$conn,
'SELECT SUM(UNIX_TIMESTAMP() - usertime.dateStarted) N '.
'FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
return $sum_ended['N'] + $sum_not_ended['N'];
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhrequentApplication';
+ return PhabricatorPhrequentApplication::class;
}
}
diff --git a/src/applications/phriction/editor/PhrictionDocumentEditEngine.php b/src/applications/phriction/editor/PhrictionDocumentEditEngine.php
index 22f56f2f57..a9c42216bc 100644
--- a/src/applications/phriction/editor/PhrictionDocumentEditEngine.php
+++ b/src/applications/phriction/editor/PhrictionDocumentEditEngine.php
@@ -1,85 +1,85 @@
<?php
final class PhrictionDocumentEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phriction.document';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Phriction Document');
}
public function getSummaryHeader() {
return pht('Edit Phriction Document Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Phriction documents.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
protected function newEditableObject() {
$viewer = $this->getViewer();
return PhrictionDocument::initializeNewDocument(
$viewer,
'/');
}
protected function newObjectQuery() {
return id(new PhrictionDocumentQuery())
->needContent(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Document');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Document');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Document: %s', $object->getContent()->getTitle());
}
protected function getObjectEditShortText($object) {
return pht('Edit Document');
}
protected function getObjectCreateShortText() {
return pht('Create Document');
}
protected function getObjectName() {
return pht('Document');
}
protected function getEditorURI() {
return '/phriction/document/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/phriction/document/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
// NOTE: For now, this engine is only to support commenting.
return PhabricatorPolicies::POLICY_NOONE;
}
protected function buildCustomEditFields($object) {
return array();
}
}
diff --git a/src/applications/phriction/editor/PhrictionTransactionEditor.php b/src/applications/phriction/editor/PhrictionTransactionEditor.php
index d59541c401..da6bd30b6c 100644
--- a/src/applications/phriction/editor/PhrictionTransactionEditor.php
+++ b/src/applications/phriction/editor/PhrictionTransactionEditor.php
@@ -1,579 +1,579 @@
<?php
final class PhrictionTransactionEditor
extends PhabricatorApplicationTransactionEditor {
const VALIDATE_CREATE_ANCESTRY = 'create';
const VALIDATE_MOVE_ANCESTRY = 'move';
private $description;
private $oldContent;
private $newContent;
private $moveAwayDocument;
private $skipAncestorCheck;
private $contentVersion;
private $processContentVersionError = true;
private $contentDiffURI;
public function setDescription($description) {
$this->description = $description;
return $this;
}
private function getDescription() {
return $this->description;
}
private function setOldContent(PhrictionContent $content) {
$this->oldContent = $content;
return $this;
}
public function getOldContent() {
return $this->oldContent;
}
private function setNewContent(PhrictionContent $content) {
$this->newContent = $content;
return $this;
}
public function getNewContent() {
return $this->newContent;
}
public function setSkipAncestorCheck($bool) {
$this->skipAncestorCheck = $bool;
return $this;
}
public function getSkipAncestorCheck() {
return $this->skipAncestorCheck;
}
public function setContentVersion($version) {
$this->contentVersion = $version;
return $this;
}
public function getContentVersion() {
return $this->contentVersion;
}
public function setProcessContentVersionError($process) {
$this->processContentVersionError = $process;
return $this;
}
public function getProcessContentVersionError() {
return $this->processContentVersionError;
}
public function setMoveAwayDocument(PhrictionDocument $document) {
$this->moveAwayDocument = $document;
return $this;
}
public function setShouldPublishContent(
PhrictionDocument $object,
$publish) {
if ($publish) {
$content_phid = $this->getNewContent()->getPHID();
} else {
$content_phid = $this->getOldContent()->getPHID();
}
$object->setContentPHID($content_phid);
return $this;
}
public function getEditorApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phriction Documents');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$this->setOldContent($object->getContent());
return parent::expandTransactions($object, $xactions);
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$xactions = parent::expandTransaction($object, $xaction);
switch ($xaction->getTransactionType()) {
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
if ($this->getIsNewObject()) {
break;
}
$content = $xaction->getNewValue();
if ($content === '') {
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(
PhrictionDocumentDeleteTransaction::TRANSACTIONTYPE)
->setNewValue(true)
->setMetadataValue('contentDelete', true);
}
break;
case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
$document = $xaction->getNewValue();
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($document->getViewPolicy());
$xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($document->getEditPolicy());
break;
default:
break;
}
return $xactions;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
if ($this->hasNewDocumentContent()) {
$content = $this->getNewDocumentContent($object);
$content
->setDocumentPHID($object->getPHID())
->save();
}
if ($this->getIsNewObject() && !$this->getSkipAncestorCheck()) {
// Stub out empty parent documents if they don't exist
$ancestral_slugs = PhabricatorSlug::getAncestry($object->getSlug());
if ($ancestral_slugs) {
$ancestors = id(new PhrictionDocumentQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withSlugs($ancestral_slugs)
->needContent(true)
->execute();
$ancestors = mpull($ancestors, null, 'getSlug');
$stub_type = PhrictionChangeType::CHANGE_STUB;
foreach ($ancestral_slugs as $slug) {
$ancestor_doc = idx($ancestors, $slug);
// We check for change type to prevent near-infinite recursion
if (!$ancestor_doc && $content->getChangeType() != $stub_type) {
$ancestor_doc = PhrictionDocument::initializeNewDocument(
$this->getActor(),
$slug);
$stub_xactions = array();
$stub_xactions[] = id(new PhrictionTransaction())
->setTransactionType(
PhrictionDocumentTitleTransaction::TRANSACTIONTYPE)
->setNewValue(PhabricatorSlug::getDefaultTitle($slug))
->setMetadataValue('stub:create:phid', $object->getPHID());
$stub_xactions[] = id(new PhrictionTransaction())
->setTransactionType(
PhrictionDocumentContentTransaction::TRANSACTIONTYPE)
->setNewValue('')
->setMetadataValue('stub:create:phid', $object->getPHID());
$stub_xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
->setNewValue($object->getViewPolicy());
$stub_xactions[] = id(new PhrictionTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
->setNewValue($object->getEditPolicy());
$sub_editor = id(new PhrictionTransactionEditor())
->setActor($this->getActor())
->setContentSource($this->getContentSource())
->setContinueOnNoEffect($this->getContinueOnNoEffect())
->setSkipAncestorCheck(true)
->setDescription(pht('Empty Parent Document'))
->applyTransactions($ancestor_doc, $stub_xactions);
}
}
}
}
if ($this->moveAwayDocument !== null) {
$move_away_xactions = array();
$move_away_xactions[] = id(new PhrictionTransaction())
->setTransactionType(
PhrictionDocumentMoveAwayTransaction::TRANSACTIONTYPE)
->setNewValue($object);
$sub_editor = id(new PhrictionTransactionEditor())
->setActor($this->getActor())
->setContentSource($this->getContentSource())
->setContinueOnNoEffect($this->getContinueOnNoEffect())
->setDescription($this->getDescription())
->applyTransactions($this->moveAwayDocument, $move_away_xactions);
}
// Compute the content diff URI for the publishing phase.
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
$params = array(
'l' => $this->getOldContent()->getVersion(),
'r' => $this->getNewContent()->getVersion(),
);
$path = '/phriction/diff/'.$object->getID().'/';
$uri = new PhutilURI($path, $params);
$this->contentDiffURI = (string)$uri;
break 2;
default:
break;
}
}
return $xactions;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return '[Phriction]';
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$this->getActingAsPHID(),
);
}
public function getMailTagsMap() {
return array(
PhrictionTransaction::MAILTAG_TITLE =>
pht("A document's title changes."),
PhrictionTransaction::MAILTAG_CONTENT =>
pht("A document's content changes."),
PhrictionTransaction::MAILTAG_DELETE =>
pht('A document is deleted.'),
PhrictionTransaction::MAILTAG_SUBSCRIBERS =>
pht('A document\'s subscribers change.'),
PhrictionTransaction::MAILTAG_OTHER =>
pht('Other document activity not listed above occurs.'),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhrictionReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$title = $object->getContent()->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject($title);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
if ($this->getIsNewObject()) {
$body->addRemarkupSection(
pht('DOCUMENT CONTENT'),
$object->getContent()->getContent());
} else if ($this->contentDiffURI) {
$body->addLinkSection(
pht('DOCUMENT DIFF'),
PhabricatorEnv::getProductionURI($this->contentDiffURI));
}
$description = $object->getContent()->getDescription();
if (strlen($description)) {
$body->addTextSection(
pht('EDIT NOTES'),
$description);
}
$body->addLinkSection(
pht('DOCUMENT DETAIL'),
PhabricatorEnv::getProductionURI(
PhrictionDocument::getSlugURI($object->getSlug())));
return $body;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->shouldSendMail($object, $xactions);
}
protected function getFeedRelatedPHIDs(
PhabricatorLiskDAO $object,
array $xactions) {
$phids = parent::getFeedRelatedPHIDs($object, $xactions);
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
$dict = $xaction->getNewValue();
$phids[] = $dict['phid'];
break;
}
}
return $phids;
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
foreach ($xactions as $xaction) {
switch ($type) {
case PhrictionDocumentContentTransaction::TRANSACTIONTYPE:
if ($xaction->getMetadataValue('stub:create:phid')) {
break;
}
if ($this->getProcessContentVersionError()) {
$error = $this->validateContentVersion($object, $type, $xaction);
if ($error) {
$this->setProcessContentVersionError(false);
$errors[] = $error;
}
}
if ($this->getIsNewObject()) {
$ancestry_errors = $this->validateAncestry(
$object,
$type,
$xaction,
self::VALIDATE_CREATE_ANCESTRY);
if ($ancestry_errors) {
$errors = array_merge($errors, $ancestry_errors);
}
}
break;
case PhrictionDocumentMoveToTransaction::TRANSACTIONTYPE:
$source_document = $xaction->getNewValue();
$ancestry_errors = $this->validateAncestry(
$object,
$type,
$xaction,
self::VALIDATE_MOVE_ANCESTRY);
if ($ancestry_errors) {
$errors = array_merge($errors, $ancestry_errors);
}
$target_document = id(new PhrictionDocumentQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withSlugs(array($object->getSlug()))
->needContent(true)
->executeOne();
// Prevent overwrites and no-op moves.
$exists = PhrictionDocumentStatus::STATUS_EXISTS;
if ($target_document) {
$message = null;
if ($target_document->getSlug() == $source_document->getSlug()) {
$message = pht(
'You can not move a document to its existing location. '.
'Choose a different location to move the document to.');
} else if ($target_document->getStatus() == $exists) {
$message = pht(
'You can not move this document there, because it would '.
'overwrite an existing document which is already at that '.
'location. Move or delete the existing document first.');
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
}
}
break;
}
}
return $errors;
}
public function validateAncestry(
PhabricatorLiskDAO $object,
$type,
PhabricatorApplicationTransaction $xaction,
$verb) {
$errors = array();
// NOTE: We use the omnipotent user for these checks because policy
// doesn't matter; existence does.
$other_doc_viewer = PhabricatorUser::getOmnipotentUser();
$ancestral_slugs = PhabricatorSlug::getAncestry($object->getSlug());
if ($ancestral_slugs) {
$ancestors = id(new PhrictionDocumentQuery())
->setViewer($other_doc_viewer)
->withSlugs($ancestral_slugs)
->execute();
$ancestors = mpull($ancestors, null, 'getSlug');
foreach ($ancestral_slugs as $slug) {
$ancestor_doc = idx($ancestors, $slug);
if (!$ancestor_doc) {
$create_uri = '/phriction/edit/?slug='.$slug;
$create_link = phutil_tag(
'a',
array(
'href' => $create_uri,
),
$slug);
switch ($verb) {
case self::VALIDATE_MOVE_ANCESTRY:
$message = pht(
'Can not move document because the parent document with '.
'slug %s does not exist!',
$create_link);
break;
case self::VALIDATE_CREATE_ANCESTRY:
$message = pht(
'Can not create document because the parent document with '.
'slug %s does not exist!',
$create_link);
break;
}
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Missing Ancestor'),
$message,
$xaction);
$errors[] = $error;
}
}
}
return $errors;
}
private function validateContentVersion(
PhabricatorLiskDAO $object,
$type,
PhabricatorApplicationTransaction $xaction) {
$error = null;
if ($this->getContentVersion() &&
($object->getMaxVersion() != $this->getContentVersion())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Edit Conflict'),
pht(
'Another user made changes to this document after you began '.
'editing it. Do you want to overwrite their changes? '.
'(If you choose to overwrite their changes, you should review '.
'the document edit history to see what you overwrote, and '.
'then make another edit to merge the changes if necessary.)'),
$xaction);
}
return $error;
}
protected function supportsSearch() {
return true;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new PhrictionDocumentHeraldAdapter())
->setDocument($object);
}
private function hasNewDocumentContent() {
return (bool)$this->newContent;
}
public function getNewDocumentContent(PhrictionDocument $document) {
if (!$this->hasNewDocumentContent()) {
$content = $this->newDocumentContent($document);
// Generate a PHID now so we can populate "contentPHID" before saving
// the document to the database: the column is not nullable so we need
// a value.
$content_phid = $content->generatePHID();
$content->setPHID($content_phid);
$document->setContentPHID($content_phid);
$document->attachContent($content);
$document->setEditedEpoch(PhabricatorTime::getNow());
$document->setMaxVersion($content->getVersion());
$this->newContent = $content;
}
return $this->newContent;
}
private function newDocumentContent(PhrictionDocument $document) {
$content = id(new PhrictionContent())
->setSlug($document->getSlug())
->setAuthorPHID($this->getActingAsPHID())
->setChangeType(PhrictionChangeType::CHANGE_EDIT)
->setTitle($this->getOldContent()->getTitle())
->setContent($this->getOldContent()->getContent())
->setDescription('');
if (phutil_nonempty_string($this->getDescription())) {
$content->setDescription($this->getDescription());
}
$content->setVersion($document->getMaxVersion() + 1);
return $content;
}
protected function getCustomWorkerState() {
return array(
'contentDiffURI' => $this->contentDiffURI,
);
}
protected function loadCustomWorkerState(array $state) {
$this->contentDiffURI = idx($state, 'contentDiffURI');
return $this;
}
}
diff --git a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
index 74de97d5fc..7eae636b3c 100644
--- a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
+++ b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
@@ -1,69 +1,69 @@
<?php
final class PhrictionDocumentHeraldAdapter extends HeraldAdapter {
private $document;
public function getAdapterApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to wiki documents being created or updated.');
}
protected function initializeNewAdapter() {
$this->document = $this->newObject();
}
protected function newObject() {
return new PhrictionDocument();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PhrictionDocument);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when a wiki document is created or updated.');
}
public function setObject($object) {
$this->document = $object;
return $this;
}
public function getObject() {
return $this->document;
}
public function setDocument(PhrictionDocument $document) {
$this->document = $document;
return $this;
}
public function getDocument() {
return $this->document;
}
public function getAdapterContentName() {
return pht('Phriction Documents');
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function getHeraldName() {
return pht('Wiki Document %d', $this->getDocument()->getID());
}
}
diff --git a/src/applications/phriction/phid/PhrictionContentPHIDType.php b/src/applications/phriction/phid/PhrictionContentPHIDType.php
index b8f39c0ef4..4db60601d9 100644
--- a/src/applications/phriction/phid/PhrictionContentPHIDType.php
+++ b/src/applications/phriction/phid/PhrictionContentPHIDType.php
@@ -1,38 +1,38 @@
<?php
final class PhrictionContentPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'WRDS';
public function getTypeName() {
return pht('Phriction Content');
}
public function newObject() {
return new PhrictionContent();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhrictionContentQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$content = $objects[$phid];
}
}
}
diff --git a/src/applications/phriction/phid/PhrictionDocumentPHIDType.php b/src/applications/phriction/phid/PhrictionDocumentPHIDType.php
index 57afdb84d6..4dcb039121 100644
--- a/src/applications/phriction/phid/PhrictionDocumentPHIDType.php
+++ b/src/applications/phriction/phid/PhrictionDocumentPHIDType.php
@@ -1,50 +1,50 @@
<?php
final class PhrictionDocumentPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'WIKI';
public function getTypeName() {
return pht('Phriction Wiki Document');
}
public function newObject() {
return new PhrictionDocument();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhrictionDocumentQuery())
->withPHIDs($phids)
->needContent(true);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$document = $objects[$phid];
$content = $document->getContent();
$title = $content->getTitle();
$slug = $document->getSlug();
$status = $document->getStatus();
$handle->setName($title);
$handle->setURI(PhrictionDocument::getSlugURI($slug));
if ($status != PhrictionDocumentStatus::STATUS_EXISTS) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/phriction/query/PhrictionContentQuery.php b/src/applications/phriction/query/PhrictionContentQuery.php
index 8ac92be351..ded328ea25 100644
--- a/src/applications/phriction/query/PhrictionContentQuery.php
+++ b/src/applications/phriction/query/PhrictionContentQuery.php
@@ -1,124 +1,124 @@
<?php
final class PhrictionContentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $documentPHIDs;
private $versions;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDocumentPHIDs(array $phids) {
$this->documentPHIDs = $phids;
return $this;
}
public function withVersions(array $versions) {
$this->versions = $versions;
return $this;
}
public function newResultObject() {
return new PhrictionContent();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'c.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'c.phid IN (%Ls)',
$this->phids);
}
if ($this->versions !== null) {
$where[] = qsprintf(
$conn,
'version IN (%Ld)',
$this->versions);
}
if ($this->documentPHIDs !== null) {
$where[] = qsprintf(
$conn,
'd.phid IN (%Ls)',
$this->documentPHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinDocumentTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T d ON d.phid = c.documentPHID',
id(new PhrictionDocument())->getTableName());
}
return $joins;
}
protected function willFilterPage(array $contents) {
$document_phids = mpull($contents, 'getDocumentPHID');
$documents = id(new PhrictionDocumentQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($document_phids)
->execute();
$documents = mpull($documents, null, 'getPHID');
foreach ($contents as $key => $content) {
$document_phid = $content->getDocumentPHID();
$document = idx($documents, $document_phid);
if (!$document) {
unset($contents[$key]);
$this->didRejectResult($content);
continue;
}
$content->attachDocument($document);
}
return $contents;
}
private function shouldJoinDocumentTable() {
if ($this->documentPHIDs !== null) {
return true;
}
return false;
}
protected function getPrimaryTableAlias() {
return 'c';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
}
diff --git a/src/applications/phriction/query/PhrictionContentSearchEngine.php b/src/applications/phriction/query/PhrictionContentSearchEngine.php
index f7cd9be2b6..5bdbaa7535 100644
--- a/src/applications/phriction/query/PhrictionContentSearchEngine.php
+++ b/src/applications/phriction/query/PhrictionContentSearchEngine.php
@@ -1,76 +1,76 @@
<?php
final class PhrictionContentSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phriction Document Content');
}
public function getApplicationClassName() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
public function newQuery() {
return new PhrictionContentQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['documentPHIDs']) {
$query->withDocumentPHIDs($map['documentPHIDs']);
}
if ($map['versions']) {
$query->withVersions($map['versions']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setKey('documentPHIDs')
->setAliases(array('document', 'documents', 'documentPHID'))
->setLabel(pht('Documents')),
id(new PhabricatorIDsSearchField())
->setKey('versions')
->setAliases(array('version')),
);
}
protected function getURI($path) {
// There's currently no web UI for this search interface, it exists purely
// to power the Conduit API.
throw new PhutilMethodNotImplementedException();
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Content'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $contents,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($contents, 'PhrictionContent');
throw new PhutilMethodNotImplementedException();
}
}
diff --git a/src/applications/phriction/query/PhrictionDocumentQuery.php b/src/applications/phriction/query/PhrictionDocumentQuery.php
index 298db97dbb..491458a128 100644
--- a/src/applications/phriction/query/PhrictionDocumentQuery.php
+++ b/src/applications/phriction/query/PhrictionDocumentQuery.php
@@ -1,398 +1,398 @@
<?php
final class PhrictionDocumentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $slugs;
private $depths;
private $slugPrefix;
private $statuses;
private $parentPaths;
private $ancestorPaths;
private $needContent;
const ORDER_HIERARCHY = 'hierarchy';
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withSlugs(array $slugs) {
$this->slugs = $slugs;
return $this;
}
public function withDepths(array $depths) {
$this->depths = $depths;
return $this;
}
public function withSlugPrefix($slug_prefix) {
$this->slugPrefix = $slug_prefix;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withParentPaths(array $paths) {
$this->parentPaths = $paths;
return $this;
}
public function withAncestorPaths(array $paths) {
$this->ancestorPaths = $paths;
return $this;
}
public function needContent($need_content) {
$this->needContent = $need_content;
return $this;
}
public function newResultObject() {
return new PhrictionDocument();
}
protected function willFilterPage(array $documents) {
if ($documents) {
$ancestor_slugs = array();
foreach ($documents as $key => $document) {
$document_slug = $document->getSlug();
foreach (PhabricatorSlug::getAncestry($document_slug) as $ancestor) {
$ancestor_slugs[$ancestor][] = $key;
}
}
if ($ancestor_slugs) {
$table = new PhrictionDocument();
$conn_r = $table->establishConnection('r');
$ancestors = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE slug IN (%Ls)',
$document->getTableName(),
array_keys($ancestor_slugs));
$ancestors = $table->loadAllFromArray($ancestors);
$ancestors = mpull($ancestors, null, 'getSlug');
foreach ($ancestor_slugs as $ancestor_slug => $document_keys) {
$ancestor = idx($ancestors, $ancestor_slug);
foreach ($document_keys as $document_key) {
$documents[$document_key]->attachAncestor(
$ancestor_slug,
$ancestor);
}
}
}
}
// To view a Phriction document, you must also be able to view all of the
// ancestor documents. Filter out documents which have ancestors that are
// not visible.
$document_map = array();
foreach ($documents as $document) {
$document_map[$document->getSlug()] = $document;
foreach ($document->getAncestors() as $key => $ancestor) {
if ($ancestor) {
$document_map[$key] = $ancestor;
}
}
}
$filtered_map = $this->applyPolicyFilter(
$document_map,
array(PhabricatorPolicyCapability::CAN_VIEW));
// Filter all of the documents where a parent is not visible.
foreach ($documents as $document_key => $document) {
// If the document itself is not visible, filter it.
if (!isset($filtered_map[$document->getSlug()])) {
$this->didRejectResult($documents[$document_key]);
unset($documents[$document_key]);
continue;
}
// If an ancestor exists but is not visible, filter the document.
foreach ($document->getAncestors() as $ancestor_key => $ancestor) {
if (!$ancestor) {
continue;
}
if (!isset($filtered_map[$ancestor_key])) {
$this->didRejectResult($documents[$document_key]);
unset($documents[$document_key]);
break;
}
}
}
if (!$documents) {
return $documents;
}
if ($this->needContent) {
$contents = id(new PhrictionContentQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($documents, 'getContentPHID'))
->execute();
$contents = mpull($contents, null, 'getPHID');
foreach ($documents as $key => $document) {
$content_phid = $document->getContentPHID();
if (empty($contents[$content_phid])) {
unset($documents[$key]);
continue;
}
$document->attachContent($contents[$content_phid]);
}
}
return $documents;
}
protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
$select = parent::buildSelectClauseParts($conn);
if ($this->shouldJoinContentTable()) {
$select[] = qsprintf($conn, 'c.title');
}
return $select;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinContentTable()) {
$content_dao = new PhrictionContent();
$joins[] = qsprintf(
$conn,
'JOIN %T c ON d.contentPHID = c.phid',
$content_dao->getTableName());
}
return $joins;
}
private function shouldJoinContentTable() {
if ($this->getOrderVector()->containsKey('title')) {
return true;
}
return false;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'd.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'd.phid IN (%Ls)',
$this->phids);
}
if ($this->slugs !== null) {
$where[] = qsprintf(
$conn,
'd.slug IN (%Ls)',
$this->slugs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'd.status IN (%Ls)',
$this->statuses);
}
if ($this->slugPrefix !== null) {
$where[] = qsprintf(
$conn,
'd.slug LIKE %>',
$this->slugPrefix);
}
if ($this->depths !== null) {
$where[] = qsprintf(
$conn,
'd.depth IN (%Ld)',
$this->depths);
}
if ($this->parentPaths !== null || $this->ancestorPaths !== null) {
$sets = array(
array(
'paths' => $this->parentPaths,
'parents' => true,
),
array(
'paths' => $this->ancestorPaths,
'parents' => false,
),
);
$paths = array();
foreach ($sets as $set) {
$set_paths = $set['paths'];
if ($set_paths === null) {
continue;
}
if (!$set_paths) {
throw new PhabricatorEmptyQueryException(
pht('No parent/ancestor paths specified.'));
}
$is_parents = $set['parents'];
foreach ($set_paths as $path) {
$path_normal = PhabricatorSlug::normalize($path);
if ($path !== $path_normal) {
throw new Exception(
pht(
'Document path "%s" is not a valid path. The normalized '.
'form of this path is "%s".',
$path,
$path_normal));
}
$depth = PhabricatorSlug::getDepth($path_normal);
if ($is_parents) {
$min_depth = $depth + 1;
$max_depth = $depth + 1;
} else {
$min_depth = $depth + 1;
$max_depth = null;
}
$paths[] = array(
$path_normal,
$min_depth,
$max_depth,
);
}
}
$path_clauses = array();
foreach ($paths as $path) {
$parts = array();
list($prefix, $min, $max) = $path;
// If we're getting children or ancestors of the root document, they
// aren't actually stored with the leading "/" in the database, so
// just skip this part of the clause.
if ($prefix !== '/') {
$parts[] = qsprintf(
$conn,
'd.slug LIKE %>',
$prefix);
}
if ($min !== null) {
$parts[] = qsprintf(
$conn,
'd.depth >= %d',
$min);
}
if ($max !== null) {
$parts[] = qsprintf(
$conn,
'd.depth <= %d',
$max);
}
if ($parts) {
$path_clauses[] = qsprintf($conn, '%LA', $parts);
}
}
if ($path_clauses) {
$where[] = qsprintf($conn, '%LO', $path_clauses);
}
}
return $where;
}
public function getBuiltinOrders() {
return parent::getBuiltinOrders() + array(
self::ORDER_HIERARCHY => array(
'vector' => array('depth', 'title', 'updated', 'id'),
'name' => pht('Hierarchy'),
),
);
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'depth' => array(
'table' => 'd',
'column' => 'depth',
'reverse' => true,
'type' => 'int',
),
'title' => array(
'table' => 'c',
'column' => 'title',
'reverse' => true,
'type' => 'string',
),
'updated' => array(
'table' => 'd',
'column' => 'editedEpoch',
'type' => 'int',
'unique' => false,
),
);
}
protected function newPagingMapFromCursorObject(
PhabricatorQueryCursor $cursor,
array $keys) {
$document = $cursor->getObject();
$map = array(
'id' => (int)$document->getID(),
'depth' => $document->getDepth(),
'updated' => (int)$document->getEditedEpoch(),
);
if (isset($keys['title'])) {
$map['title'] = $cursor->getRawRowProperty('title');
}
return $map;
}
protected function getPrimaryTableAlias() {
return 'd';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
}
diff --git a/src/applications/phriction/query/PhrictionDocumentSearchEngine.php b/src/applications/phriction/query/PhrictionDocumentSearchEngine.php
index 49a332268b..cf59159298 100644
--- a/src/applications/phriction/query/PhrictionDocumentSearchEngine.php
+++ b/src/applications/phriction/query/PhrictionDocumentSearchEngine.php
@@ -1,161 +1,161 @@
<?php
final class PhrictionDocumentSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Wiki Documents');
}
public function getApplicationClassName() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
public function newQuery() {
return id(new PhrictionDocumentQuery())
->needContent(true);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
if ($map['paths']) {
$query->withSlugs($map['paths']);
}
if ($map['parentPaths']) {
$query->withParentPaths($map['parentPaths']);
}
if ($map['ancestorPaths']) {
$query->withAncestorPaths($map['ancestorPaths']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Status'))
->setOptions(PhrictionDocumentStatus::getStatusMap()),
id(new PhabricatorSearchStringListField())
->setKey('paths')
->setIsHidden(true)
->setLabel(pht('Paths')),
id(new PhabricatorSearchStringListField())
->setKey('parentPaths')
->setIsHidden(true)
->setLabel(pht('Parent Paths')),
id(new PhabricatorSearchStringListField())
->setKey('ancestorPaths')
->setIsHidden(true)
->setLabel(pht('Ancestor Paths')),
);
}
protected function getURI($path) {
return '/phriction/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active'),
'all' => pht('All'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query->setParameter(
'statuses',
array(
PhrictionDocumentStatus::STATUS_EXISTS,
));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $documents,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($documents as $document) {
$content = $document->getContent();
$phids[] = $content->getAuthorPHID();
}
return $phids;
}
protected function renderResultList(
array $documents,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($documents, 'PhrictionDocument');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($documents as $document) {
$content = $document->getContent();
$slug = $document->getSlug();
$author_phid = $content->getAuthorPHID();
$slug_uri = PhrictionDocument::getSlugURI($slug);
$byline = pht(
'Edited by %s',
$handles[$author_phid]->renderLink());
$updated = phabricator_datetime(
$content->getDateCreated(),
$viewer);
$item = id(new PHUIObjectItemView())
->setHeader($content->getTitle())
->setObject($document)
->setHref($slug_uri)
->addByline($byline)
->addIcon('none', $updated);
$item->addAttribute($slug_uri);
$icon = $document->getStatusIcon();
$color = $document->getStatusColor();
$label = $document->getStatusDisplayName();
$item->setStatusIcon("{$icon} {$color}", $label);
if (!$document->isActive()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No documents found.'));
return $result;
}
}
diff --git a/src/applications/phriction/typeahead/PhrictionDocumentDatasource.php b/src/applications/phriction/typeahead/PhrictionDocumentDatasource.php
index 8e16051840..fbc48af97d 100644
--- a/src/applications/phriction/typeahead/PhrictionDocumentDatasource.php
+++ b/src/applications/phriction/typeahead/PhrictionDocumentDatasource.php
@@ -1,79 +1,79 @@
<?php
final class PhrictionDocumentDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Documents');
}
public function getPlaceholderText() {
return pht('Type a document name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPhrictionApplication';
+ return PhabricatorPhrictionApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$app_type = pht('Wiki Document');
$mid_dot = "\xC2\xB7";
$query = id(new PhrictionDocumentQuery())
->setViewer($viewer)
->needContent(true);
$this->applyFerretConstraints(
$query,
id(new PhrictionDocument())->newFerretEngine(),
'title',
$this->getRawQuery());
$documents = $query->execute();
$results = array();
foreach ($documents as $document) {
$content = $document->getContent();
if ($document->isActive()) {
$closed = null;
} else {
$closed = $document->getStatusDisplayName();
}
$slug = $document->getSlug();
$title = $content->getTitle();
// For some time the search result was
// just mentioning the document slug.
// Now, it also mentions the application type.
// Example: "Wiki Document - /foo/bar"
$display_type = sprintf(
'%s %s %s',
$app_type,
$mid_dot,
$slug);
$sprite = 'phabricator-search-icon phui-font-fa phui-icon-view fa-book';
$autocomplete = '[[ '.$slug.' ]]';
$result = id(new PhabricatorTypeaheadResult())
->setName($title)
->setDisplayName($title)
->setURI($document->getURI())
->setPHID($document->getPHID())
->setDisplayType($display_type)
->setPriorityType('wiki')
->setImageSprite($sprite)
->setAutocomplete($autocomplete)
->setClosed($closed);
$results[] = $result;
}
return $results;
}
}
diff --git a/src/applications/phurl/editor/PhabricatorPhurlURLEditEngine.php b/src/applications/phurl/editor/PhabricatorPhurlURLEditEngine.php
index 12a4d2672f..efadadd745 100644
--- a/src/applications/phurl/editor/PhabricatorPhurlURLEditEngine.php
+++ b/src/applications/phurl/editor/PhabricatorPhurlURLEditEngine.php
@@ -1,114 +1,114 @@
<?php
final class PhabricatorPhurlURLEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'phurl.url';
public function getEngineName() {
return pht('Phurl');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Phurl Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Phurl.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return PhabricatorPhurlURL::initializeNewPhurlURL($this->getViewer());
}
protected function newObjectQuery() {
return new PhabricatorPhurlURLQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New URL');
}
protected function getObjectEditTitleText($object) {
return pht('Edit URL: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create URL');
}
protected function getObjectName() {
return pht('URL');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('url/edit/');
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorPhurlURLCreateCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('URL name.'))
->setIsRequired(true)
->setConduitTypeDescription(pht('New URL name.'))
->setTransactionType(
PhabricatorPhurlURLNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('url')
->setLabel(pht('URL'))
->setDescription(pht('The URL to shorten.'))
->setConduitTypeDescription(pht('New URL.'))
->setValue($object->getLongURL())
->setIsRequired(true)
->setTransactionType(
PhabricatorPhurlURLLongURLTransaction::TRANSACTIONTYPE),
id(new PhabricatorTextEditField())
->setKey('alias')
->setLabel(pht('Alias'))
->setIsRequired(true)
->setTransactionType(
PhabricatorPhurlURLAliasTransaction::TRANSACTIONTYPE)
->setDescription(pht('The alias to give the URL.'))
->setConduitTypeDescription(pht('New alias.'))
->setValue($object->getAlias()),
id(new PhabricatorRemarkupEditField())
->setKey('description')
->setLabel(pht('Description'))
->setDescription(pht('URL long description.'))
->setConduitTypeDescription(pht('New URL description.'))
->setTransactionType(
PhabricatorPhurlURLDescriptionTransaction::TRANSACTIONTYPE)
->setValue($object->getDescription()),
);
}
}
diff --git a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php
index 49f290c343..a67a1c425d 100644
--- a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php
+++ b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php
@@ -1,115 +1,115 @@
<?php
final class PhabricatorPhurlURLEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Phurl');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this URL.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
PhabricatorPhurlURLTransaction::MAILTAG_DETAILS =>
pht(
"A URL's details change."),
);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Phurl]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->getActingAsPHID();
return $phids;
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject("U{$id}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$description = $object->getDescription();
$body = parent::buildMailBody($object, $xactions);
if (strlen($description)) {
$body->addRemarkupSection(
pht('URL DESCRIPTION'),
$object->getDescription());
}
$body->addLinkSection(
pht('URL DETAIL'),
PhabricatorEnv::getProductionURI('/U'.$object->getID()));
return $body;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
PhabricatorPhurlURLAliasTransaction::TRANSACTIONTYPE,
pht('Duplicate'),
pht('This alias is already in use.'),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorPhurlURLReplyHandler())
->setMailReceiver($object);
}
}
diff --git a/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php b/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php
index 979b25c791..14bdb11df5 100644
--- a/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php
+++ b/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php
@@ -1,74 +1,74 @@
<?php
final class PhabricatorPhurlURLPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PHRL';
public function getTypeName() {
return pht('URL');
}
public function newObject() {
return new PhabricatorPhurlURL();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPhurlURLQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$url = $objects[$phid];
$id = $url->getID();
$name = $url->getName();
$full_name = $url->getMonogram().' '.$name;
$handle
->setName($name)
->setFullName($full_name)
->setURI($url->getURI());
}
}
public function canLoadNamedObject($name) {
return preg_match('/^U[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorPhurlURLQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
index c30cedf09d..cc82264c45 100644
--- a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
+++ b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php
@@ -1,108 +1,108 @@
<?php
final class PhabricatorPhurlURLQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $names;
private $longURLs;
private $aliases;
private $authorPHIDs;
public function newResultObject() {
return new PhabricatorPhurlURL();
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
id(new PhabricatorPhurlURLNameNgrams()),
$ngrams);
}
public function withLongURLs(array $long_urls) {
$this->longURLs = $long_urls;
return $this;
}
public function withAliases(array $aliases) {
$this->aliases = $aliases;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'url.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'url.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'url.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'url.name IN (%Ls)',
$this->names);
}
if ($this->longURLs !== null) {
$where[] = qsprintf(
$conn,
'url.longURL IN (%Ls)',
$this->longURLs);
}
if ($this->aliases !== null) {
$where[] = qsprintf(
$conn,
'url.alias IN (%Ls)',
$this->aliases);
}
return $where;
}
protected function getPrimaryTableAlias() {
return 'url';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
}
diff --git a/src/applications/phurl/query/PhabricatorPhurlURLSearchEngine.php b/src/applications/phurl/query/PhabricatorPhurlURLSearchEngine.php
index 8814b25b9c..a3a38c8ee9 100644
--- a/src/applications/phurl/query/PhabricatorPhurlURLSearchEngine.php
+++ b/src/applications/phurl/query/PhabricatorPhurlURLSearchEngine.php
@@ -1,147 +1,147 @@
<?php
final class PhabricatorPhurlURLSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Phurl URLs');
}
public function getApplicationClassName() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
public function newQuery() {
return new PhabricatorPhurlURLQuery();
}
protected function shouldShowOrderField() {
return true;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Created By'))
->setKey('authorPHIDs')
->setDatasource(new PhabricatorPeopleUserFunctionDatasource()),
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
->setKey('name')
->setDescription(pht('Search for Phurl URLs by name substring.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Aliases'))
->setKey('aliases')
->setDescription(pht('Search for Phurl URLs by alias.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Long URLs'))
->setKey('longurls')
->setDescription(
pht('Search for Phurl URLs by the non-shortened URL.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['name'] !== null) {
$query->withNameNgrams($map['name']);
}
if ($map['aliases']) {
$query->withAliases($map['aliases']);
}
if ($map['longurls']) {
$query->withLongURLs($map['longurls']);
}
return $query;
}
protected function getURI($path) {
return '/phurl/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All URLs'),
'authored' => pht('Authored'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer = $this->requireViewer();
switch ($query_key) {
case 'authored':
return $query->setParameter('authorPHIDs', array($viewer->getPHID()));
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $urls,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($urls, 'PhabricatorPhurlURL');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$handles = $viewer->loadHandles(mpull($urls, 'getAuthorPHID'));
foreach ($urls as $url) {
$name = $url->getName();
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($url)
->setObjectName('U'.$url->getID())
->setHeader($name)
->setHref('/U'.$url->getID())
->addAttribute($url->getAlias())
->addAttribute($url->getLongURL());
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No URLs found.'));
return $result;
}
protected function getNewUserBody() {
$create_uri = id(new PhabricatorPhurlURLEditEngine())
->getEditURI();
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Shorten a URL'))
->setHref($create_uri)
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Create reusable, memorable, shorter URLs for easy accessibility.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php b/src/applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php
index f8d3cda0cd..77eabd8a28 100644
--- a/src/applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php
+++ b/src/applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php
@@ -1,36 +1,36 @@
<?php
final class PhabricatorPhurlURLDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Phurl URLs');
}
public function getPlaceholderText() {
return pht('Select a phurl...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPhurlApplication';
+ return PhabricatorPhurlApplication::class;
}
public function loadResults() {
$query = id(new PhabricatorPhurlURLQuery());
$urls = $this->executeQuery($query);
$results = array();
foreach ($urls as $url) {
$result = id(new PhabricatorTypeaheadResult())
->setDisplayName($url->getName())
->setName($url->getName()." ".$url->getAlias())
->setPHID($url->getPHID())
->setAutocomplete('(('.$url->getAlias().'))')
->addAttribute($url->getLongURL());
$results[] = $result;
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php b/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php
index ed75561327..afc84dd853 100644
--- a/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php
+++ b/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorPolicyPHIDTypePolicy extends PhabricatorPHIDType {
const TYPECONST = 'PLCY';
public function getTypeName() {
return pht('Policy');
}
public function newObject() {
return new PhabricatorPolicy();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPolicyApplication';
+ return PhabricatorPolicyApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPolicyQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$policy = $objects[$phid];
$handle->setName($policy->getName());
$handle->setURI($policy->getHref());
}
}
}
diff --git a/src/applications/policy/query/PhabricatorPolicyQuery.php b/src/applications/policy/query/PhabricatorPolicyQuery.php
index 9bd6ba5994..58e03d325f 100644
--- a/src/applications/policy/query/PhabricatorPolicyQuery.php
+++ b/src/applications/policy/query/PhabricatorPolicyQuery.php
@@ -1,432 +1,432 @@
<?php
final class PhabricatorPolicyQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $object;
private $phids;
const OBJECT_POLICY_PREFIX = 'obj.';
public function setObject(PhabricatorPolicyInterface $object) {
$this->object = $object;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public static function loadPolicies(
PhabricatorUser $viewer,
PhabricatorPolicyInterface $object) {
$results = array();
$map = array();
foreach ($object->getCapabilities() as $capability) {
$map[$capability] = $object->getPolicy($capability);
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->withPHIDs($map)
->execute();
foreach ($map as $capability => $phid) {
$results[$capability] = $policies[$phid];
}
return $results;
}
public static function renderPolicyDescriptions(
PhabricatorUser $viewer,
PhabricatorPolicyInterface $object) {
$policies = self::loadPolicies($viewer, $object);
foreach ($policies as $capability => $policy) {
$policies[$capability] = $policy->newRef($viewer)
->newCapabilityLink($object, $capability);
}
return $policies;
}
protected function loadPage() {
if ($this->object && $this->phids) {
throw new Exception(
pht(
'You can not issue a policy query with both %s and %s.',
'setObject()',
'setPHIDs()'));
} else if ($this->object) {
$phids = $this->loadObjectPolicyPHIDs();
} else {
$phids = $this->phids;
}
$phids = array_fuse($phids);
$results = array();
// First, load global policies.
foreach (self::getGlobalPolicies() as $phid => $policy) {
if (isset($phids[$phid])) {
$results[$phid] = $policy;
unset($phids[$phid]);
}
}
// Now, load object policies.
foreach (self::getObjectPolicies($this->object) as $phid => $policy) {
if (isset($phids[$phid])) {
$results[$phid] = $policy;
unset($phids[$phid]);
}
}
// If we still need policies, we're going to have to fetch data. Bucket
// the remaining policies into rule-based policies and handle-based
// policies.
if ($phids) {
$rule_policies = array();
$handle_policies = array();
foreach ($phids as $phid) {
$phid_type = phid_get_type($phid);
if ($phid_type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) {
$rule_policies[$phid] = $phid;
} else {
$handle_policies[$phid] = $phid;
}
}
if ($handle_policies) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($handle_policies)
->execute();
foreach ($handle_policies as $phid) {
$results[$phid] = PhabricatorPolicy::newFromPolicyAndHandle(
$phid,
$handles[$phid]);
}
}
if ($rule_policies) {
$rules = id(new PhabricatorPolicy())->loadAllWhere(
'phid IN (%Ls)',
$rule_policies);
$results += mpull($rules, null, 'getPHID');
}
}
$results = msort($results, 'getSortKey');
return $results;
}
public static function isGlobalPolicy($policy) {
$global_policies = self::getGlobalPolicies();
if (isset($global_policies[$policy])) {
return true;
}
return false;
}
public static function getGlobalPolicy($policy) {
if (!self::isGlobalPolicy($policy)) {
throw new Exception(pht("Policy '%s' is not a global policy!", $policy));
}
return idx(self::getGlobalPolicies(), $policy);
}
private static function getGlobalPolicies() {
static $constants = array(
PhabricatorPolicies::POLICY_PUBLIC,
PhabricatorPolicies::POLICY_USER,
PhabricatorPolicies::POLICY_ADMIN,
PhabricatorPolicies::POLICY_NOONE,
);
$results = array();
foreach ($constants as $constant) {
$results[$constant] = id(new PhabricatorPolicy())
->setType(PhabricatorPolicyType::TYPE_GLOBAL)
->setPHID($constant)
->setName(self::getGlobalPolicyName($constant))
->setShortName(self::getGlobalPolicyShortName($constant))
->makeEphemeral();
}
return $results;
}
private static function getGlobalPolicyName($policy) {
switch ($policy) {
case PhabricatorPolicies::POLICY_PUBLIC:
return pht('Public (No Login Required)');
case PhabricatorPolicies::POLICY_USER:
return pht('All Users');
case PhabricatorPolicies::POLICY_ADMIN:
return pht('Administrators');
case PhabricatorPolicies::POLICY_NOONE:
return pht('No One');
default:
return pht('Unknown Policy');
}
}
private static function getGlobalPolicyShortName($policy) {
switch ($policy) {
case PhabricatorPolicies::POLICY_PUBLIC:
return pht('Public');
default:
return null;
}
}
private function loadObjectPolicyPHIDs() {
$phids = array();
$viewer = $this->getViewer();
if ($viewer->getPHID()) {
$pref_key = PhabricatorPolicyFavoritesSetting::SETTINGKEY;
$favorite_limit = 10;
$default_limit = 5;
// If possible, show the user's 10 most recently used projects.
$favorites = $viewer->getUserSetting($pref_key);
if (!is_array($favorites)) {
$favorites = array();
}
$favorite_phids = array_keys($favorites);
$favorite_phids = array_slice($favorite_phids, -$favorite_limit);
if ($favorite_phids) {
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withPHIDs($favorite_phids)
->withIsMilestone(false)
->setLimit($favorite_limit)
->execute();
$projects = mpull($projects, null, 'getPHID');
} else {
$projects = array();
}
// If we didn't find enough favorites, add some default projects. These
// are just arbitrary projects that the viewer is a member of, but may
// be useful on smaller installs and for new users until they can use
// the control enough time to establish useful favorites.
if (count($projects) < $default_limit) {
$default_projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs(array($viewer->getPHID()))
->withIsMilestone(false)
->withStatuses(
array(
PhabricatorProjectStatus::STATUS_ACTIVE,
))
->setLimit($default_limit)
->execute();
$default_projects = mpull($default_projects, null, 'getPHID');
$projects = $projects + $default_projects;
$projects = array_slice($projects, 0, $default_limit);
}
foreach ($projects as $project) {
$phids[] = $project->getPHID();
}
// Include the "current viewer" policy. This improves consistency, but
// is also useful for creating private instances of normally-shared object
// types, like repositories.
$phids[] = $viewer->getPHID();
}
$capabilities = $this->object->getCapabilities();
foreach ($capabilities as $capability) {
$policy = $this->object->getPolicy($capability);
if (!$policy) {
continue;
}
$phids[] = $policy;
}
// If this install doesn't have "Public" enabled, don't include it as an
// option unless the object already has a "Public" policy. In this case we
// retain the policy but enforce it as though it was "All Users".
$show_public = PhabricatorEnv::getEnvConfig('policy.allow-public');
foreach (self::getGlobalPolicies() as $phid => $policy) {
if ($phid == PhabricatorPolicies::POLICY_PUBLIC) {
if (!$show_public) {
continue;
}
}
$phids[] = $phid;
}
foreach (self::getObjectPolicies($this->object) as $phid => $policy) {
$phids[] = $phid;
}
return $phids;
}
protected function shouldDisablePolicyFiltering() {
// Policy filtering of policies is currently perilous and not required by
// the application.
return true;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPolicyApplication';
+ return PhabricatorPolicyApplication::class;
}
public static function isSpecialPolicy($identifier) {
if ($identifier === null) {
return true;
}
if (self::isObjectPolicy($identifier)) {
return true;
}
if (self::isGlobalPolicy($identifier)) {
return true;
}
return false;
}
/* -( Object Policies )---------------------------------------------------- */
public static function isObjectPolicy($identifier) {
$prefix = self::OBJECT_POLICY_PREFIX;
return !strncmp($identifier, $prefix, strlen($prefix));
}
public static function getObjectPolicy($identifier) {
if (!self::isObjectPolicy($identifier)) {
return null;
}
$policies = self::getObjectPolicies(null);
return idx($policies, $identifier);
}
public static function getObjectPolicyRule($identifier) {
if (!self::isObjectPolicy($identifier)) {
return null;
}
$rules = self::getObjectPolicyRules(null);
return idx($rules, $identifier);
}
public static function getObjectPolicies($object) {
$rule_map = self::getObjectPolicyRules($object);
$results = array();
foreach ($rule_map as $key => $rule) {
$results[$key] = id(new PhabricatorPolicy())
->setType(PhabricatorPolicyType::TYPE_OBJECT)
->setPHID($key)
->setIcon($rule->getObjectPolicyIcon())
->setName($rule->getObjectPolicyName())
->setShortName($rule->getObjectPolicyShortName())
->makeEphemeral();
}
return $results;
}
public static function getObjectPolicyRules($object) {
$rules = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorPolicyRule')
->execute();
$results = array();
foreach ($rules as $rule) {
$key = $rule->getObjectPolicyKey();
if (!$key) {
continue;
}
$full_key = $rule->getObjectPolicyFullKey();
if (isset($results[$full_key])) {
throw new Exception(
pht(
'Two policy rules (of classes "%s" and "%s") define the same '.
'object policy key ("%s"), but each object policy rule must use '.
'a unique key.',
get_class($rule),
get_class($results[$full_key]),
$key));
}
$results[$full_key] = $rule;
}
if ($object !== null) {
foreach ($results as $key => $rule) {
if (!$rule->canApplyToObject($object)) {
unset($results[$key]);
}
}
}
return $results;
}
public static function getDefaultPolicyForObject(
PhabricatorUser $viewer,
PhabricatorPolicyInterface $object,
$capability) {
$phid = $object->getPHID();
if (!$phid) {
return null;
}
$type = phid_get_type($phid);
$map = self::getDefaultObjectTypePolicyMap();
if (empty($map[$type][$capability])) {
return null;
}
$policy_phid = $map[$type][$capability];
return id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->withPHIDs(array($policy_phid))
->executeOne();
}
private static function getDefaultObjectTypePolicyMap() {
static $map;
if ($map === null) {
$map = array();
$apps = PhabricatorApplication::getAllApplications();
foreach ($apps as $app) {
$map += $app->getDefaultObjectTypePolicyMap();
}
}
return $map;
}
}
diff --git a/src/applications/ponder/editor/PonderEditor.php b/src/applications/ponder/editor/PonderEditor.php
index fcfa981f16..76615175e9 100644
--- a/src/applications/ponder/editor/PonderEditor.php
+++ b/src/applications/ponder/editor/PonderEditor.php
@@ -1,14 +1,14 @@
<?php
abstract class PonderEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
protected function getMailSubjectPrefix() {
return '[Ponder]';
}
}
diff --git a/src/applications/ponder/editor/PonderQuestionEditEngine.php b/src/applications/ponder/editor/PonderQuestionEditEngine.php
index 640f657ad1..0365226666 100644
--- a/src/applications/ponder/editor/PonderQuestionEditEngine.php
+++ b/src/applications/ponder/editor/PonderQuestionEditEngine.php
@@ -1,109 +1,109 @@
<?php
final class PonderQuestionEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'ponder.question';
public function getEngineName() {
return pht('Ponder Question');
}
public function getEngineApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
public function getSummaryHeader() {
return pht('Configure Ponder Question Forms');
}
public function getSummaryText() {
return pht('Configure creation and editing forms in Ponder Questions.');
}
public function isEngineConfigurable() {
return false;
}
protected function newEditableObject() {
return PonderQuestion::initializeNewQuestion($this->getViewer());
}
protected function newObjectQuery() {
return new PonderQuestionQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Question');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Question: %s', $object->getTitle());
}
protected function getObjectEditShortText($object) {
return $object->getTitle();
}
protected function getObjectCreateShortText() {
return pht('New Question');
}
protected function getObjectName() {
return pht('Question');
}
protected function getObjectCreateCancelURI($object) {
return $this->getApplication()->getApplicationURI('/');
}
protected function getEditorURI() {
return $this->getApplication()->getApplicationURI('question/edit/');
}
protected function getObjectViewURI($object) {
return $object->getViewURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('title')
->setLabel(pht('Question'))
->setDescription(pht('Question title.'))
->setConduitTypeDescription(pht('New question title.'))
->setTransactionType(
PonderQuestionTitleTransaction::TRANSACTIONTYPE)
->setValue($object->getTitle())
->setIsRequired(true),
id(new PhabricatorRemarkupEditField())
->setKey('content')
->setLabel(pht('Details'))
->setDescription(pht('Long details of the question.'))
->setConduitTypeDescription(pht('New question details.'))
->setValue($object->getContent())
->setTransactionType(
PonderQuestionContentTransaction::TRANSACTIONTYPE),
id(new PhabricatorRemarkupEditField())
->setKey('answerWiki')
->setLabel(pht('Answer Summary'))
->setDescription(pht('Answer summary of the question.'))
->setConduitTypeDescription(pht('New question answer summary.'))
->setValue($object->getAnswerWiki())
->setTransactionType(
PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
->setDescription(pht('Status of the question.'))
->setConduitTypeDescription(pht('New question status.'))
->setValue($object->getStatus())
->setTransactionType(
PonderQuestionStatusTransaction::TRANSACTIONTYPE)
->setOptions(PonderQuestionStatus::getQuestionStatusMap()),
);
}
}
diff --git a/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php b/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
index f9434c7f78..6a46f56b3e 100644
--- a/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
+++ b/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
@@ -1,70 +1,70 @@
<?php
final class HeraldPonderQuestionAdapter extends HeraldAdapter {
private $question;
protected function newObject() {
return new PonderQuestion();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to questions being created or updated.');
}
protected function initializeNewAdapter() {
$this->question = $this->newObject();
}
public function isTestAdapterForObject($object) {
return ($object instanceof PonderQuestion);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when a question is created or updated.');
}
public function setObject($object) {
$this->question = $object;
return $this;
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setQuestion(PonderQuestion $question) {
$this->question = $question;
return $this;
}
public function getObject() {
return $this->question;
}
public function getAdapterContentName() {
return pht('Ponder Questions');
}
public function getHeraldName() {
return 'Q'.$this->getObject()->getID();
}
}
diff --git a/src/applications/ponder/phid/PonderAnswerPHIDType.php b/src/applications/ponder/phid/PonderAnswerPHIDType.php
index be148af2f2..19ce39b59d 100644
--- a/src/applications/ponder/phid/PonderAnswerPHIDType.php
+++ b/src/applications/ponder/phid/PonderAnswerPHIDType.php
@@ -1,44 +1,44 @@
<?php
final class PonderAnswerPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'ANSW';
public function getTypeName() {
return pht('Ponder Answer');
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
public function newObject() {
return new PonderAnswer();
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PonderAnswerQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$answer = $objects[$phid];
$id = $answer->getID();
$question = $answer->getQuestion();
$question_title = $question->getFullTitle();
$handle->setName(pht('%s (Answer %s)', $question_title, $id));
$handle->setURI($answer->getURI());
}
}
}
diff --git a/src/applications/ponder/phid/PonderQuestionPHIDType.php b/src/applications/ponder/phid/PonderQuestionPHIDType.php
index 9bdd80aae6..b135e9fc3c 100644
--- a/src/applications/ponder/phid/PonderQuestionPHIDType.php
+++ b/src/applications/ponder/phid/PonderQuestionPHIDType.php
@@ -1,72 +1,72 @@
<?php
final class PonderQuestionPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'QUES';
public function getTypeName() {
return pht('Ponder Question');
}
public function newObject() {
return new PonderQuestion();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PonderQuestionQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$question = $objects[$phid];
$id = $question->getID();
$handle->setName("Q{$id}");
$handle->setURI("/Q{$id}");
$handle->setFullName($question->getFullTitle());
}
}
public function canLoadNamedObject($name) {
return preg_match('/^Q\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PonderQuestionQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/ponder/query/PonderAnswerQuery.php b/src/applications/ponder/query/PonderAnswerQuery.php
index f100f05ae3..9b362cf71e 100644
--- a/src/applications/ponder/query/PonderAnswerQuery.php
+++ b/src/applications/ponder/query/PonderAnswerQuery.php
@@ -1,84 +1,84 @@
<?php
final class PonderAnswerQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $questionIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withQuestionIDs(array $ids) {
$this->questionIDs = $ids;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
return $where;
}
public function newResultObject() {
return new PonderAnswer();
}
protected function willFilterPage(array $answers) {
$questions = id(new PonderQuestionQuery())
->setViewer($this->getViewer())
->withIDs(mpull($answers, 'getQuestionID'))
->execute();
foreach ($answers as $key => $answer) {
$question = idx($questions, $answer->getQuestionID());
if (!$question) {
unset($answers[$key]);
continue;
}
$answer->attachQuestion($question);
}
return $answers;
}
public function getQueryApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
}
diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php
index 323f34aac5..535e38ab51 100644
--- a/src/applications/ponder/query/PonderQuestionQuery.php
+++ b/src/applications/ponder/query/PonderQuestionQuery.php
@@ -1,150 +1,150 @@
<?php
final class PonderQuestionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $status;
private $authorPHIDs;
private $answererPHIDs;
private $needProjectPHIDs;
private $needAnswers;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withStatuses($status) {
$this->status = $status;
return $this;
}
public function withAnswererPHIDs(array $phids) {
$this->answererPHIDs = $phids;
return $this;
}
public function needAnswers($need_answers) {
$this->needAnswers = $need_answers;
return $this;
}
public function needProjectPHIDs($need_projects) {
$this->needProjectPHIDs = $need_projects;
return $this;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'q.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'q.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'q.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->status !== null) {
$where[] = qsprintf(
$conn,
'q.status IN (%Ls)',
$this->status);
}
return $where;
}
public function newResultObject() {
return new PonderQuestion();
}
protected function willFilterPage(array $questions) {
$phids = mpull($questions, 'getPHID');
if ($this->needAnswers) {
$aquery = id(new PonderAnswerQuery())
->setViewer($this->getViewer())
->setOrderVector(array('-id'))
->withQuestionIDs(mpull($questions, 'getID'));
$answers = $aquery->execute();
$answers = mgroup($answers, 'getQuestionID');
foreach ($questions as $question) {
$question_answers = idx($answers, $question->getID(), array());
$question->attachAnswers(mpull($question_answers, null, 'getPHID'));
}
}
if ($this->needProjectPHIDs) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($phids)
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($questions as $question) {
$project_phids = $edge_query->getDestinationPHIDs(
array($question->getPHID()));
$question->attachProjectPHIDs($project_phids);
}
}
return $questions;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->answererPHIDs) {
$answer_table = new PonderAnswer();
$joins[] = qsprintf(
$conn,
'JOIN %T a ON a.questionID = q.id AND a.authorPHID IN (%Ls)',
$answer_table->getTableName(),
$this->answererPHIDs);
}
return $joins;
}
protected function getPrimaryTableAlias() {
return 'q';
}
public function getQueryApplicationClass() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
}
diff --git a/src/applications/ponder/query/PonderQuestionSearchEngine.php b/src/applications/ponder/query/PonderQuestionSearchEngine.php
index ecca1a91e5..ab08637124 100644
--- a/src/applications/ponder/query/PonderQuestionSearchEngine.php
+++ b/src/applications/ponder/query/PonderQuestionSearchEngine.php
@@ -1,205 +1,205 @@
<?php
final class PonderQuestionSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Ponder Questions');
}
public function getApplicationClassName() {
- return 'PhabricatorPonderApplication';
+ return PhabricatorPonderApplication::class;
}
public function newQuery() {
return id(new PonderQuestionQuery())
->needProjectPHIDs(true);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['answerers']) {
$query->withAnswererPHIDs($map['answerers']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setKey('authorPHIDs')
->setAliases(array('authors'))
->setLabel(pht('Authors')),
id(new PhabricatorUsersSearchField())
->setKey('answerers')
->setAliases(array('answerers'))
->setLabel(pht('Answered By')),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Status'))
->setKey('statuses')
->setOptions(PonderQuestionStatus::getQuestionStatusMap()),
);
}
protected function getURI($path) {
return '/ponder/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'recent' => pht('Recent Questions'),
'open' => pht('Open Questions'),
'resolved' => pht('Resolved Questions'),
'all' => pht('All Questions'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
$names['answered'] = pht('Answered');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'open':
return $query->setParameter(
'statuses', array(PonderQuestionStatus::STATUS_OPEN));
case 'recent':
return $query->setParameter(
'statuses', array(
PonderQuestionStatus::STATUS_OPEN,
PonderQuestionStatus::STATUS_CLOSED_RESOLVED,
));
case 'resolved':
return $query->setParameter(
'statuses', array(PonderQuestionStatus::STATUS_CLOSED_RESOLVED));
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
case 'answered':
return $query->setParameter(
'answerers',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $questions,
PhabricatorSavedQuery $query) {
return mpull($questions, 'getAuthorPHID');
}
protected function renderResultList(
array $questions,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($questions, 'PonderQuestion');
$viewer = $this->requireViewer();
$proj_phids = array();
foreach ($questions as $question) {
foreach ($question->getProjectPHIDs() as $project_phid) {
$proj_phids[] = $project_phid;
}
}
$proj_handles = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs($proj_phids)
->execute();
$view = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($questions as $question) {
$color = PonderQuestionStatus::getQuestionStatusTagColor(
$question->getStatus());
$icon = PonderQuestionStatus::getQuestionStatusIcon(
$question->getStatus());
$full_status = PonderQuestionStatus::getQuestionStatusFullName(
$question->getStatus());
$item = new PHUIObjectItemView();
$item->setObjectName('Q'.$question->getID());
$item->setHeader($question->getTitle());
$item->setHref('/Q'.$question->getID());
$item->setObject($question);
$item->setStatusIcon($icon.' '.$color, $full_status);
$project_handles = array_select_keys(
$proj_handles,
$question->getProjectPHIDs());
$created_date = phabricator_date($question->getDateCreated(), $viewer);
$item->addIcon('none', $created_date);
$item->addByline(
pht(
'Asked by %s',
$handles[$question->getAuthorPHID()]->renderLink()));
// Render Closed Questions as striked in query results
$item->setDisabled($question->isStatusClosed());
$item->addAttribute(
pht(
'%s Answer(s)',
new PhutilNumber($question->getAnswerCount())));
if ($project_handles) {
$item->addAttribute(
id(new PHUIHandleTagListView())
->setLimit(4)
->setSlim(true)
->setHandles($project_handles));
}
$view->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($view);
$result->setNoDataString(pht('No questions found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Ask a Question'))
->setHref('/ponder/question/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('A simple questions and answers application for your teams.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/project/editor/PhabricatorProjectColumnTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectColumnTransactionEditor.php
index e0becc3470..3ebae4c247 100644
--- a/src/applications/project/editor/PhabricatorProjectColumnTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectColumnTransactionEditor.php
@@ -1,22 +1,22 @@
<?php
final class PhabricatorProjectColumnTransactionEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Workboard Columns');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this column.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
index 9c6e5cf4cc..ab9fca1109 100644
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -1,463 +1,463 @@
<?php
final class PhabricatorProjectTransactionEditor
extends PhabricatorApplicationTransactionEditor {
private $isMilestone;
private function setIsMilestone($is_milestone) {
$this->isMilestone = $is_milestone;
return $this;
}
public function getIsMilestone() {
return $this->isMilestone;
}
public function getEditorApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Projects');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this project.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PhabricatorTransactions::TYPE_JOIN_POLICY;
return $types;
}
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$errors = array();
// Prevent creating projects which are both subprojects and milestones,
// since this does not make sense, won't work, and will break everything.
$parent_xaction = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectParentTransaction::TRANSACTIONTYPE:
case PhabricatorProjectMilestoneTransaction::TRANSACTIONTYPE:
if ($xaction->getNewValue() === null) {
continue 2;
}
if (!$parent_xaction) {
$parent_xaction = $xaction;
continue 2;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$xaction->getTransactionType(),
pht('Invalid'),
pht(
'When creating a project, specify a maximum of one parent '.
'project or milestone project. A project can not be both a '.
'subproject and a milestone.'),
$xaction);
break 2;
}
}
$is_milestone = $this->getIsMilestone();
$is_parent = $object->getHasSubprojects();
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_EDGE:
$type = $xaction->getMetadataValue('edge:type');
if ($type != PhabricatorProjectProjectHasMemberEdgeType::EDGECONST) {
break;
}
if ($is_parent) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$xaction->getTransactionType(),
pht('Invalid'),
pht(
'You can not change members of a project with subprojects '.
'directly. Members of any subproject are automatically '.
'members of the parent project.'),
$xaction);
}
if ($is_milestone) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$xaction->getTransactionType(),
pht('Invalid'),
pht(
'You can not change members of a milestone. Members of the '.
'parent project are automatically members of the milestone.'),
$xaction);
}
break;
}
}
return $errors;
}
protected function willPublish(PhabricatorLiskDAO $object, array $xactions) {
// NOTE: We're using the omnipotent user here because the original actor
// may no longer have permission to view the object.
return id(new PhabricatorProjectQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($object->getPHID()))
->needAncestorMembers(true)
->executeOne();
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailSubjectPrefix() {
return pht('[Project]');
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$this->getActingAsPHID(),
);
}
protected function getMailCc(PhabricatorLiskDAO $object) {
return array();
}
public function getMailTagsMap() {
return array(
PhabricatorProjectTransaction::MAILTAG_METADATA =>
pht('Project name, hashtags, icon, image, or color changes.'),
PhabricatorProjectTransaction::MAILTAG_MEMBERS =>
pht('Project membership changes.'),
PhabricatorProjectTransaction::MAILTAG_WATCHERS =>
pht('Project watcher list changes.'),
PhabricatorProjectTransaction::MAILTAG_OTHER =>
pht('Other project activity not listed above occurs.'),
);
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ProjectReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$name = $object->getName();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$uri = '/project/profile/'.$object->getID().'/';
$body->addLinkSection(
pht('PROJECT DETAIL'),
PhabricatorEnv::getProductionURI($uri));
return $body;
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function supportsSearch() {
return true;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$materialize = false;
$new_parent = null;
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorTransactions::TYPE_EDGE:
switch ($xaction->getMetadataValue('edge:type')) {
case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST:
$materialize = true;
break;
}
break;
case PhabricatorProjectParentTransaction::TRANSACTIONTYPE:
case PhabricatorProjectMilestoneTransaction::TRANSACTIONTYPE:
$materialize = true;
$new_parent = $object->getParentProject();
break;
}
}
if ($new_parent) {
// If we just created the first subproject of this parent, we want to
// copy all of the real members to the subproject.
if (!$new_parent->getHasSubprojects()) {
$member_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
$project_members = PhabricatorEdgeQuery::loadDestinationPHIDs(
$new_parent->getPHID(),
$member_type);
if ($project_members) {
$editor = id(new PhabricatorEdgeEditor());
foreach ($project_members as $phid) {
$editor->addEdge($object->getPHID(), $member_type, $phid);
}
$editor->save();
}
}
}
// TODO: We should dump an informational transaction onto the parent
// project to show that we created the sub-thing.
if ($materialize) {
id(new PhabricatorProjectsMembershipIndexEngineExtension())
->rematerialize($object);
}
if ($new_parent) {
id(new PhabricatorProjectsMembershipIndexEngineExtension())
->rematerialize($new_parent);
}
// See PHI1046. Milestones are always in the Space of their parent project.
// Synchronize the database values to match the application values.
$conn = $object->establishConnection('w');
queryfx(
$conn,
'UPDATE %R SET spacePHID = %ns
WHERE parentProjectPHID = %s AND milestoneNumber IS NOT NULL',
$object,
$object->getSpacePHID(),
$object->getPHID());
return parent::applyFinalEffects($object, $xactions);
}
public function addSlug(PhabricatorProject $project, $slug, $force) {
$slug = PhabricatorSlug::normalizeProjectSlug($slug);
$table = new PhabricatorProjectSlug();
$project_phid = $project->getPHID();
if ($force) {
// If we have the `$force` flag set, we only want to ignore an existing
// slug if it's for the same project. We'll error on collisions with
// other projects.
$current = $table->loadOneWhere(
'slug = %s AND projectPHID = %s',
$slug,
$project_phid);
} else {
// Without the `$force` flag, we'll just return without doing anything
// if any other project already has the slug.
$current = $table->loadOneWhere(
'slug = %s',
$slug);
}
if ($current) {
return;
}
return id(new PhabricatorProjectSlug())
->setSlug($slug)
->setProjectPHID($project_phid)
->save();
}
public function removeSlugs(PhabricatorProject $project, array $slugs) {
// Do not allow removing the project's primary slug which the edit form
// may allow through a series of renames/moves. See T15636
if (($key = array_search($project->getPrimarySlug(), $slugs)) !== false) {
unset($slugs[$key]);
}
if (!$slugs) {
return;
}
// We're going to try to delete both the literal and normalized versions
// of all slugs. This allows us to destroy old slugs that are no longer
// valid.
foreach ($this->normalizeSlugs($slugs) as $slug) {
$slugs[] = $slug;
}
$objects = id(new PhabricatorProjectSlug())->loadAllWhere(
'projectPHID = %s AND slug IN (%Ls)',
$project->getPHID(),
$slugs);
foreach ($objects as $object) {
$object->delete();
}
}
public function normalizeSlugs(array $slugs) {
foreach ($slugs as $key => $slug) {
$slugs[$key] = PhabricatorSlug::normalizeProjectSlug($slug);
}
$slugs = array_unique($slugs);
$slugs = array_values($slugs);
return $slugs;
}
protected function adjustObjectForPolicyChecks(
PhabricatorLiskDAO $object,
array $xactions) {
$copy = parent::adjustObjectForPolicyChecks($object, $xactions);
$type_edge = PhabricatorTransactions::TYPE_EDGE;
$edgetype_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
// See T13462. If we're creating a milestone, set a dummy milestone
// number so the project behaves like a milestone and uses milestone
// policy rules. Otherwise, we'll end up checking the default policies
// (which are not relevant to milestones) instead of the parent project
// policies (which are the correct policies).
if ($this->getIsMilestone() && !$copy->isMilestone()) {
$copy->setMilestoneNumber(1);
}
$hint = null;
if ($this->getIsMilestone()) {
// See T13462. If we're creating a milestone, predict that the members
// of the newly created milestone will be the same as the members of the
// parent project, since this is the governing rule.
$parent = $copy->getParentProject();
$parent = id(new PhabricatorProjectQuery())
->setViewer($this->getActor())
->withPHIDs(array($parent->getPHID()))
->needMembers(true)
->executeOne();
$members = $parent->getMemberPHIDs();
$hint = array_fuse($members);
} else {
$member_xaction = null;
foreach ($xactions as $xaction) {
if ($xaction->getTransactionType() !== $type_edge) {
continue;
}
$edgetype = $xaction->getMetadataValue('edge:type');
if ($edgetype !== $edgetype_member) {
continue;
}
$member_xaction = $xaction;
}
if ($member_xaction) {
$object_phid = $object->getPHID();
if ($object_phid) {
$project = id(new PhabricatorProjectQuery())
->setViewer($this->getActor())
->withPHIDs(array($object_phid))
->needMembers(true)
->executeOne();
$members = $project->getMemberPHIDs();
} else {
$members = array();
}
$clone_xaction = clone $member_xaction;
$hint = $this->getPHIDTransactionNewValue($clone_xaction, $members);
$hint = array_fuse($hint);
}
}
if ($hint !== null) {
$rule = new PhabricatorProjectMembersPolicyRule();
PhabricatorPolicyRule::passTransactionHintToRule(
$copy,
$rule,
$hint);
}
return $copy;
}
protected function expandTransactions(
PhabricatorLiskDAO $object,
array $xactions) {
$actor = $this->getActor();
$actor_phid = $actor->getPHID();
$results = parent::expandTransactions($object, $xactions);
$is_milestone = $object->isMilestone();
foreach ($xactions as $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProjectMilestoneTransaction::TRANSACTIONTYPE:
if ($xaction->getNewValue() !== null) {
$is_milestone = true;
}
break;
}
}
$this->setIsMilestone($is_milestone);
return $results;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
// Herald rules may run on behalf of other users and need to execute
// membership checks against ancestors.
$project = id(new PhabricatorProjectQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($object->getPHID()))
->needAncestorMembers(true)
->executeOne();
return id(new PhabricatorProjectHeraldAdapter())
->setProject($project);
}
}
diff --git a/src/applications/project/editor/PhabricatorProjectTriggerEditor.php b/src/applications/project/editor/PhabricatorProjectTriggerEditor.php
index 9014fd6f16..6ac1644fb4 100644
--- a/src/applications/project/editor/PhabricatorProjectTriggerEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTriggerEditor.php
@@ -1,34 +1,34 @@
<?php
final class PhabricatorProjectTriggerEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Triggers');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this trigger.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php
index 1c84932656..51cd840d3d 100644
--- a/src/applications/project/engine/PhabricatorProjectEditEngine.php
+++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php
@@ -1,326 +1,326 @@
<?php
final class PhabricatorProjectEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'projects.project';
private $parentProject;
private $milestoneProject;
public function setParentProject(PhabricatorProject $parent_project) {
$this->parentProject = $parent_project;
return $this;
}
public function getParentProject() {
return $this->parentProject;
}
public function setMilestoneProject(PhabricatorProject $milestone_project) {
$this->milestoneProject = $milestone_project;
return $this;
}
public function getMilestoneProject() {
return $this->milestoneProject;
}
public function isDefaultQuickCreateEngine() {
return true;
}
public function getQuickCreateOrderVector() {
return id(new PhutilSortVector())->addInt(200);
}
public function getEngineName() {
return pht('Projects');
}
public function getSummaryHeader() {
return pht('Configure Project Forms');
}
public function getSummaryText() {
return pht('Configure forms for creating projects.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function newEditableObject() {
$parent = nonempty($this->parentProject, $this->milestoneProject);
return PhabricatorProject::initializeNewProject(
$this->getViewer(),
$parent);
}
protected function newObjectQuery() {
return id(new PhabricatorProjectQuery())
->needSlugs(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Project');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Project: %s', $object->getName());
}
protected function getObjectEditShortText($object) {
return $object->getName();
}
protected function getObjectCreateShortText() {
return pht('Create Project');
}
protected function getObjectName() {
return pht('Project');
}
protected function getObjectViewURI($object) {
if ($this->getIsCreate()) {
return $object->getURI();
} else {
$id = $object->getID();
return "/project/manage/{$id}/";
}
}
protected function getObjectCreateCancelURI($object) {
$parent = $this->getParentProject();
$milestone = $this->getMilestoneProject();
if ($parent || $milestone) {
$id = nonempty($parent, $milestone)->getID();
return "/project/subprojects/{$id}/";
}
return parent::getObjectCreateCancelURI($object);
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
ProjectCreateProjectsCapability::CAPABILITY);
}
protected function willConfigureFields($object, array $fields) {
$is_milestone = ($this->getMilestoneProject() || $object->isMilestone());
$unavailable = array(
PhabricatorTransactions::TYPE_VIEW_POLICY,
PhabricatorTransactions::TYPE_EDIT_POLICY,
PhabricatorTransactions::TYPE_JOIN_POLICY,
PhabricatorTransactions::TYPE_SPACE,
PhabricatorProjectIconTransaction::TRANSACTIONTYPE,
PhabricatorProjectColorTransaction::TRANSACTIONTYPE,
);
$unavailable = array_fuse($unavailable);
if ($is_milestone) {
foreach ($fields as $key => $field) {
$xaction_type = $field->getTransactionType();
if (isset($unavailable[$xaction_type])) {
unset($fields[$key]);
}
}
}
return $fields;
}
protected function newBuiltinEngineConfigurations() {
$configuration = head(parent::newBuiltinEngineConfigurations());
// TODO: This whole method is clumsy, and the ordering for the custom
// field is especially clumsy. Maybe try to make this more natural to
// express.
$configuration
->setFieldOrder(
array(
'parent',
'milestone',
'milestone.previous',
'name',
'std:project:internal:description',
'icon',
'color',
'slugs',
));
return array(
$configuration,
);
}
protected function buildCustomEditFields($object) {
$slugs = mpull($object->getSlugs(), 'getSlug');
$slugs = array_fuse($slugs);
unset($slugs[$object->getPrimarySlug()]);
$slugs = array_values($slugs);
$milestone = $this->getMilestoneProject();
$parent = $this->getParentProject();
if ($parent) {
$parent_phid = $parent->getPHID();
} else {
$parent_phid = null;
}
$previous_milestone_phid = null;
if ($milestone) {
$milestone_phid = $milestone->getPHID();
// Load the current milestone so we can show the user a hint about what
// it was called, so they don't have to remember if the next one should
// be "Sprint 287" or "Sprint 278".
$number = ($milestone->loadNextMilestoneNumber() - 1);
if ($number > 0) {
$previous_milestone = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withParentProjectPHIDs(array($milestone->getPHID()))
->withIsMilestone(true)
->withMilestoneNumberBetween($number, $number)
->executeOne();
if ($previous_milestone) {
$previous_milestone_phid = $previous_milestone->getPHID();
}
}
} else {
$milestone_phid = null;
}
$fields = array(
id(new PhabricatorHandlesEditField())
->setKey('parent')
->setLabel(pht('Parent'))
->setDescription(pht('Create a subproject of an existing project.'))
->setConduitDescription(
pht('Choose a parent project to create a subproject beneath.'))
->setConduitTypeDescription(pht('PHID of the parent project.'))
->setAliases(array('parentPHID'))
->setTransactionType(
PhabricatorProjectParentTransaction::TRANSACTIONTYPE)
->setHandleParameterType(new AphrontPHIDHTTPParameterType())
->setSingleValue($parent_phid)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setIsLocked(true),
id(new PhabricatorHandlesEditField())
->setKey('milestone')
->setLabel(pht('Milestone Of'))
->setDescription(pht('Parent project to create a milestone for.'))
->setConduitDescription(
pht('Choose a parent project to create a new milestone for.'))
->setConduitTypeDescription(pht('PHID of the parent project.'))
->setAliases(array('milestonePHID'))
->setTransactionType(
PhabricatorProjectMilestoneTransaction::TRANSACTIONTYPE)
->setHandleParameterType(new AphrontPHIDHTTPParameterType())
->setSingleValue($milestone_phid)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setIsLocked(true),
id(new PhabricatorHandlesEditField())
->setKey('milestone.previous')
->setLabel(pht('Previous Milestone'))
->setSingleValue($previous_milestone_phid)
->setIsReorderable(false)
->setIsDefaultable(false)
->setIsLockable(false)
->setIsLocked(true),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setTransactionType(PhabricatorProjectNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setDescription(pht('Project name.'))
->setConduitDescription(pht('Rename the project'))
->setConduitTypeDescription(pht('New project name.'))
->setValue($object->getName()),
id(new PhabricatorIconSetEditField())
->setKey('icon')
->setLabel(pht('Icon'))
->setTransactionType(
PhabricatorProjectIconTransaction::TRANSACTIONTYPE)
->setIconSet(new PhabricatorProjectIconSet())
->setDescription(pht('Project icon.'))
->setConduitDescription(pht('Change the project icon.'))
->setConduitTypeDescription(pht('New project icon.'))
->setValue($object->getIcon()),
id(new PhabricatorSelectEditField())
->setKey('color')
->setLabel(pht('Color'))
->setTransactionType(
PhabricatorProjectColorTransaction::TRANSACTIONTYPE)
->setOptions(PhabricatorProjectIconSet::getColorMap())
->setDescription(pht('Project tag color.'))
->setConduitDescription(pht('Change the project tag color.'))
->setConduitTypeDescription(pht('New project tag color.'))
->setValue($object->getColor()),
id(new PhabricatorStringListEditField())
->setKey('slugs')
->setLabel(pht('Additional Hashtags'))
->setTransactionType(
PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE)
->setDescription(pht('Additional project slugs.'))
->setConduitDescription(pht('Change project slugs.'))
->setConduitTypeDescription(pht('New list of slugs.'))
->setValue($slugs),
);
$can_edit_members = (!$milestone) &&
(!$object->isMilestone()) &&
(!$object->getHasSubprojects());
if ($can_edit_members) {
// Show this on the web UI when creating a project, but not when editing
// one. It is always available via Conduit.
$show_field = (bool)$this->getIsCreate();
$members_field = id(new PhabricatorUsersEditField())
->setKey('members')
->setAliases(array('memberPHIDs'))
->setLabel(pht('Initial Members'))
->setIsFormField($show_field)
->setUseEdgeTransactions(true)
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue(
'edge:type',
PhabricatorProjectProjectHasMemberEdgeType::EDGECONST)
->setDescription(pht('Initial project members.'))
->setConduitDescription(pht('Set project members.'))
->setConduitTypeDescription(pht('New list of members.'))
->setValue(array());
$members_field->setViewer($this->getViewer());
$edit_add = $members_field->getConduitEditType('members.add')
->setConduitDescription(pht('Add members.'));
$edit_set = $members_field->getConduitEditType('members.set')
->setConduitDescription(
pht('Set members, overwriting the current value.'));
$edit_rem = $members_field->getConduitEditType('members.remove')
->setConduitDescription(pht('Remove members.'));
$fields[] = $members_field;
}
return $fields;
}
}
diff --git a/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php b/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php
index 72f064a5c6..43c46a878c 100644
--- a/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php
+++ b/src/applications/project/herald/PhabricatorProjectHeraldAdapter.php
@@ -1,59 +1,59 @@
<?php
final class PhabricatorProjectHeraldAdapter extends HeraldAdapter {
private $project;
protected function newObject() {
return new PhabricatorProject();
}
public function getAdapterApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getAdapterContentDescription() {
return pht('React to projects being created or updated.');
}
protected function initializeNewAdapter() {
$this->project = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setProject(PhabricatorProject $project) {
$this->project = $project;
return $this;
}
public function getProject() {
return $this->project;
}
public function getObject() {
return $this->project;
}
public function getAdapterContentName() {
return pht('Projects');
}
public function getHeraldName() {
return pht('Project %s', $this->getProject()->getName());
}
}
diff --git a/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php b/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php
index c58bb44671..cfcf56f8c0 100644
--- a/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php
+++ b/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php
@@ -1,48 +1,48 @@
<?php
final class PhabricatorProjectColumnPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PCOL';
public function getTypeName() {
return pht('Project Column');
}
public function getTypeIcon() {
return 'fa-columns bluegrey';
}
public function newObject() {
return new PhabricatorProjectColumn();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorProjectColumnQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$column = $objects[$phid];
$handle->setName($column->getDisplayName());
$handle->setURI($column->getWorkboardURI());
if ($column->isHidden()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
}
diff --git a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
index 4a9cfbb8a6..e032f98588 100644
--- a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
+++ b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php
@@ -1,121 +1,121 @@
<?php
final class PhabricatorProjectProjectPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PROJ';
public function getTypeName() {
return pht('Project');
}
public function getTypeIcon() {
return 'fa-briefcase bluegrey';
}
public function newObject() {
return new PhabricatorProject();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorProjectQuery())
->withPHIDs($phids)
->needImages(true);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$project = $objects[$phid];
$name = $project->getDisplayName();
$id = $project->getID();
$slug = $project->getPrimarySlug();
$handle->setName($name);
if (phutil_nonempty_string($slug)) {
$handle->setObjectName('#'.$slug);
$handle->setMailStampName('#'.$slug);
$handle->setURI("/tag/{$slug}/");
} else {
// We set the name to the project's PHID to avoid a parse error when a
// project has no hashtag (as is the case with milestones by default).
// See T12659 for more details.
$handle->setCommandLineObjectName($project->getPHID());
$handle->setURI("/project/view/{$id}/");
}
$handle->setImageURI($project->getProfileImageURI());
$handle->setIcon($project->getDisplayIconIcon());
$handle->setTagColor($project->getDisplayColor());
if ($project->isArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public static function getProjectMonogramPatternFragment() {
// NOTE: See some discussion in ProjectRemarkupRule.
return '[^\s,#]+';
}
public function canLoadNamedObject($name) {
$fragment = self::getProjectMonogramPatternFragment();
return preg_match('/^#'.$fragment.'$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
// If the user types "#YoloSwag", we still want to match "#yoloswag", so
// we normalize, query, and then map back to the original inputs.
$map = array();
foreach ($names as $key => $slug) {
$map[$this->normalizeSlug(substr($slug, 1))][] = $slug;
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($query->getViewer())
->withSlugs(array_keys($map))
->needSlugs(true)
->execute();
$result = array();
foreach ($projects as $project) {
$slugs = $project->getSlugs();
$slug_strs = mpull($slugs, 'getSlug');
foreach ($slug_strs as $slug) {
$slug_map = idx($map, $slug, array());
foreach ($slug_map as $original) {
$result[$original] = $project;
}
}
}
return $result;
}
private function normalizeSlug($slug) {
// NOTE: We're using phutil_utf8_strtolower() (and not PhabricatorSlug's
// normalize() method) because this normalization should be only somewhat
// liberal. We want "#YOLO" to match against "#yolo", but "#\\yo!!lo"
// should not. normalize() strips out most punctuation and leads to
// excessively aggressive matches.
return phutil_utf8_strtolower($slug);
}
}
diff --git a/src/applications/project/phid/PhabricatorProjectTriggerPHIDType.php b/src/applications/project/phid/PhabricatorProjectTriggerPHIDType.php
index 346b0e69fa..cdcd3c1146 100644
--- a/src/applications/project/phid/PhabricatorProjectTriggerPHIDType.php
+++ b/src/applications/project/phid/PhabricatorProjectTriggerPHIDType.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorProjectTriggerPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'WTRG';
public function getTypeName() {
return pht('Trigger');
}
public function getTypeIcon() {
return 'fa-exclamation-triangle';
}
public function newObject() {
return new PhabricatorProjectTrigger();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorProjectTriggerQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$trigger = $objects[$phid];
$handle->setName($trigger->getDisplayName());
$handle->setURI($trigger->getURI());
}
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
index 2673902780..c4f9818a4a 100644
--- a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorProjectColumnPositionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $boardPHIDs;
private $objectPHIDs;
private $columnPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withBoardPHIDs(array $board_phids) {
$this->boardPHIDs = $board_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withColumnPHIDs(array $column_phids) {
$this->columnPHIDs = $column_phids;
return $this;
}
public function newResultObject() {
return new PhabricatorProjectColumnPosition();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->boardPHIDs !== null) {
$where[] = qsprintf(
$conn,
'boardPHID IN (%Ls)',
$this->boardPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->columnPHIDs !== null) {
$where[] = qsprintf(
$conn,
'columnPHID IN (%Ls)',
$this->columnPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnQuery.php b/src/applications/project/query/PhabricatorProjectColumnQuery.php
index 478d872cb4..6c1763623a 100644
--- a/src/applications/project/query/PhabricatorProjectColumnQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnQuery.php
@@ -1,231 +1,231 @@
<?php
final class PhabricatorProjectColumnQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $projectPHIDs;
private $proxyPHIDs;
private $statuses;
private $isProxyColumn;
private $triggerPHIDs;
private $needTriggers;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProjectPHIDs(array $project_phids) {
$this->projectPHIDs = $project_phids;
return $this;
}
public function withProxyPHIDs(array $proxy_phids) {
$this->proxyPHIDs = $proxy_phids;
return $this;
}
public function withStatuses(array $status) {
$this->statuses = $status;
return $this;
}
public function withIsProxyColumn($is_proxy) {
$this->isProxyColumn = $is_proxy;
return $this;
}
public function withTriggerPHIDs(array $trigger_phids) {
$this->triggerPHIDs = $trigger_phids;
return $this;
}
public function needTriggers($need_triggers) {
$this->needTriggers = true;
return $this;
}
public function newResultObject() {
return new PhabricatorProjectColumn();
}
protected function willFilterPage(array $page) {
$projects = array();
$project_phids = array_filter(mpull($page, 'getProjectPHID'));
if ($project_phids) {
$projects = id(new PhabricatorProjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->execute();
$projects = mpull($projects, null, 'getPHID');
}
foreach ($page as $key => $column) {
$phid = $column->getProjectPHID();
$project = idx($projects, $phid);
if (!$project) {
$this->didRejectResult($page[$key]);
unset($page[$key]);
continue;
}
$column->attachProject($project);
}
$proxy_phids = array_filter(mpull($page, 'getProjectPHID'));
return $page;
}
protected function didFilterPage(array $page) {
$proxy_phids = array();
foreach ($page as $column) {
$proxy_phid = $column->getProxyPHID();
if ($proxy_phid !== null) {
$proxy_phids[$proxy_phid] = $proxy_phid;
}
}
if ($proxy_phids) {
$proxies = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($proxy_phids)
->execute();
$proxies = mpull($proxies, null, 'getPHID');
} else {
$proxies = array();
}
foreach ($page as $key => $column) {
$proxy_phid = $column->getProxyPHID();
if ($proxy_phid !== null) {
$proxy = idx($proxies, $proxy_phid);
// Only attach valid proxies, so we don't end up getting surprised if
// an install somehow gets junk into their database.
if (!($proxy instanceof PhabricatorColumnProxyInterface)) {
$proxy = null;
}
if (!$proxy) {
$this->didRejectResult($column);
unset($page[$key]);
continue;
}
} else {
$proxy = null;
}
$column->attachProxy($proxy);
}
if ($this->needTriggers) {
$trigger_phids = array();
foreach ($page as $column) {
if ($column->canHaveTrigger()) {
$trigger_phid = $column->getTriggerPHID();
if ($trigger_phid) {
$trigger_phids[] = $trigger_phid;
}
}
}
if ($trigger_phids) {
$triggers = id(new PhabricatorProjectTriggerQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($trigger_phids)
->execute();
$triggers = mpull($triggers, null, 'getPHID');
} else {
$triggers = array();
}
foreach ($page as $column) {
$trigger = null;
if ($column->canHaveTrigger()) {
$trigger_phid = $column->getTriggerPHID();
if ($trigger_phid) {
$trigger = idx($triggers, $trigger_phid);
}
}
$column->attachTrigger($trigger);
}
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->projectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'projectPHID IN (%Ls)',
$this->projectPHIDs);
}
if ($this->proxyPHIDs !== null) {
$where[] = qsprintf(
$conn,
'proxyPHID IN (%Ls)',
$this->proxyPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ld)',
$this->statuses);
}
if ($this->triggerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'triggerPHID IN (%Ls)',
$this->triggerPHIDs);
}
if ($this->isProxyColumn !== null) {
if ($this->isProxyColumn) {
$where[] = qsprintf($conn, 'proxyPHID IS NOT NULL');
} else {
$where[] = qsprintf($conn, 'proxyPHID IS NULL');
}
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnSearchEngine.php b/src/applications/project/query/PhabricatorProjectColumnSearchEngine.php
index 68fe1e7eb0..49702b11ea 100644
--- a/src/applications/project/query/PhabricatorProjectColumnSearchEngine.php
+++ b/src/applications/project/query/PhabricatorProjectColumnSearchEngine.php
@@ -1,78 +1,78 @@
<?php
final class PhabricatorProjectColumnSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Workboard Columns');
}
public function getApplicationClassName() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function canUseInPanelContext() {
return false;
}
public function newQuery() {
return new PhabricatorProjectColumnQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Projects'))
->setKey('projectPHIDs')
->setConduitKey('projects')
->setAliases(array('project', 'projects', 'projectPHID')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['projectPHIDs']) {
$query->withProjectPHIDs($map['projectPHIDs']);
}
return $query;
}
protected function getURI($path) {
// NOTE: There's no way to query columns in the web UI, at least for
// the moment.
return null;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $projects,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($projects, 'PhabricatorProjectColumn');
$viewer = $this->requireViewer();
return null;
}
}
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
index b02fa647a2..7b1ee9afec 100644
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -1,897 +1,897 @@
<?php
final class PhabricatorProjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
private $watcherPHIDs;
private $slugs;
private $slugNormals;
private $slugMap;
private $allSlugs;
private $names;
private $namePrefixes;
private $nameTokens;
private $icons;
private $colors;
private $ancestorPHIDs;
private $parentPHIDs;
private $isMilestone;
private $hasSubprojects;
private $minDepth;
private $maxDepth;
private $minMilestoneNumber;
private $maxMilestoneNumber;
private $subtypes;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ACTIVE = 'status-active';
const STATUS_ARCHIVED = 'status-archived';
private $statuses;
private $needSlugs;
private $needMembers;
private $needAncestorMembers;
private $needWatchers;
private $needImages;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withMemberPHIDs(array $member_phids) {
$this->memberPHIDs = $member_phids;
return $this;
}
public function withWatcherPHIDs(array $watcher_phids) {
$this->watcherPHIDs = $watcher_phids;
return $this;
}
public function withSlugs(array $slugs) {
$this->slugs = $slugs;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNamePrefixes(array $prefixes) {
$this->namePrefixes = $prefixes;
return $this;
}
public function withNameTokens(array $tokens) {
$this->nameTokens = array_values($tokens);
return $this;
}
public function withIcons(array $icons) {
$this->icons = $icons;
return $this;
}
public function withColors(array $colors) {
$this->colors = $colors;
return $this;
}
public function withParentProjectPHIDs($parent_phids) {
$this->parentPHIDs = $parent_phids;
return $this;
}
public function withAncestorProjectPHIDs($ancestor_phids) {
$this->ancestorPHIDs = $ancestor_phids;
return $this;
}
public function withIsMilestone($is_milestone) {
$this->isMilestone = $is_milestone;
return $this;
}
public function withHasSubprojects($has_subprojects) {
$this->hasSubprojects = $has_subprojects;
return $this;
}
public function withDepthBetween($min, $max) {
$this->minDepth = $min;
$this->maxDepth = $max;
return $this;
}
public function withMilestoneNumberBetween($min, $max) {
$this->minMilestoneNumber = $min;
$this->maxMilestoneNumber = $max;
return $this;
}
public function withSubtypes(array $subtypes) {
$this->subtypes = $subtypes;
return $this;
}
public function needMembers($need_members) {
$this->needMembers = $need_members;
return $this;
}
public function needAncestorMembers($need_ancestor_members) {
$this->needAncestorMembers = $need_ancestor_members;
return $this;
}
public function needWatchers($need_watchers) {
$this->needWatchers = $need_watchers;
return $this;
}
public function needImages($need_images) {
$this->needImages = $need_images;
return $this;
}
public function needSlugs($need_slugs) {
$this->needSlugs = $need_slugs;
return $this;
}
public function newResultObject() {
return new PhabricatorProject();
}
protected function getDefaultOrderVector() {
return array('name');
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'reverse' => true,
'type' => 'string',
'unique' => true,
),
'milestoneNumber' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'milestoneNumber',
'type' => 'int',
),
'status' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'status',
'type' => 'int',
),
);
}
protected function newPagingMapFromPartialObject($object) {
return array(
'id' => (int)$object->getID(),
'name' => $object->getName(),
'status' => $object->getStatus(),
);
}
public function getSlugMap() {
if ($this->slugMap === null) {
throw new PhutilInvalidStateException('execute');
}
return $this->slugMap;
}
protected function willExecute() {
$this->slugMap = array();
$this->slugNormals = array();
$this->allSlugs = array();
if ($this->slugs) {
foreach ($this->slugs as $slug) {
if (PhabricatorSlug::isValidProjectSlug($slug)) {
$normal = PhabricatorSlug::normalizeProjectSlug($slug);
$this->slugNormals[$slug] = $normal;
$this->allSlugs[$normal] = $normal;
}
// NOTE: At least for now, we query for the normalized slugs but also
// for the slugs exactly as entered. This allows older projects with
// slugs that are no longer valid to continue to work.
$this->allSlugs[$slug] = $slug;
}
}
}
protected function willFilterPage(array $projects) {
$ancestor_paths = array();
foreach ($projects as $project) {
foreach ($project->getAncestorProjectPaths() as $path) {
$ancestor_paths[$path] = $path;
}
}
if ($ancestor_paths) {
$ancestors = id(new PhabricatorProject())->loadAllWhere(
'projectPath IN (%Ls)',
$ancestor_paths);
} else {
$ancestors = array();
}
$projects = $this->linkProjectGraph($projects, $ancestors);
$viewer_phid = $this->getViewer()->getPHID();
$material_type = PhabricatorProjectMaterializedMemberEdgeType::EDGECONST;
$watcher_type = PhabricatorObjectHasWatcherEdgeType::EDGECONST;
$types = array();
$types[] = $material_type;
if ($this->needWatchers) {
$types[] = $watcher_type;
}
$all_graph = $this->getAllReachableAncestors($projects);
// See T13484. If the graph is damaged (and contains a cycle or an edge
// pointing at a project which has been destroyed), some of the nodes we
// started with may be filtered out by reachability tests. If any of the
// projects we are linking up don't have available ancestors, filter them
// out.
foreach ($projects as $key => $project) {
$project_phid = $project->getPHID();
if (!isset($all_graph[$project_phid])) {
$this->didRejectResult($project);
unset($projects[$key]);
continue;
}
}
if (!$projects) {
return array();
}
// NOTE: Although we may not need much information about ancestors, we
// always need to test if the viewer is a member, because we will return
// ancestor projects to the policy filter via ExtendedPolicy calls. If
// we skip populating membership data on a parent, the policy framework
// will think the user is not a member of the parent project.
$all_sources = array();
foreach ($all_graph as $project) {
// For milestones, we need parent members.
if ($project->isMilestone()) {
$parent_phid = $project->getParentProjectPHID();
$all_sources[$parent_phid] = $parent_phid;
}
$phid = $project->getPHID();
$all_sources[$phid] = $phid;
}
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($all_sources)
->withEdgeTypes($types);
$need_all_edges =
$this->needMembers ||
$this->needWatchers ||
$this->needAncestorMembers;
// If we only need to know if the viewer is a member, we can restrict
// the query to just their PHID.
$any_edges = true;
if (!$need_all_edges) {
if ($viewer_phid) {
$edge_query->withDestinationPHIDs(array($viewer_phid));
} else {
// If we don't need members or watchers and don't have a viewer PHID
// (viewer is logged-out or omnipotent), they'll never be a member
// so we don't need to issue this query at all.
$any_edges = false;
}
}
if ($any_edges) {
$edge_query->execute();
}
$membership_projects = array();
foreach ($all_graph as $project) {
$project_phid = $project->getPHID();
if ($project->isMilestone()) {
$source_phids = array($project->getParentProjectPHID());
} else {
$source_phids = array($project_phid);
}
if ($any_edges) {
$member_phids = $edge_query->getDestinationPHIDs(
$source_phids,
array($material_type));
} else {
$member_phids = array();
}
if (in_array($viewer_phid, $member_phids)) {
$membership_projects[$project_phid] = $project;
}
if ($this->needMembers || $this->needAncestorMembers) {
$project->attachMemberPHIDs($member_phids);
}
if ($this->needWatchers) {
$watcher_phids = $edge_query->getDestinationPHIDs(
array($project_phid),
array($watcher_type));
$project->attachWatcherPHIDs($watcher_phids);
$project->setIsUserWatcher(
$viewer_phid,
in_array($viewer_phid, $watcher_phids));
}
}
// If we loaded ancestor members, we've already populated membership
// lists above, so we can skip this step.
if (!$this->needAncestorMembers) {
$member_graph = $this->getAllReachableAncestors($membership_projects);
foreach ($all_graph as $phid => $project) {
$is_member = isset($member_graph[$phid]);
$project->setIsUserMember($viewer_phid, $is_member);
}
}
return $projects;
}
protected function didFilterPage(array $projects) {
$viewer = $this->getViewer();
if ($this->needImages) {
$need_images = $projects;
// First, try to load custom profile images for any projects with custom
// images.
$file_phids = array();
foreach ($need_images as $key => $project) {
$image_phid = $project->getProfileImagePHID();
if ($image_phid) {
$file_phids[$key] = $image_phid;
}
}
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($viewer)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($file_phids as $key => $image_phid) {
$file = idx($files, $image_phid);
if (!$file) {
continue;
}
$need_images[$key]->attachProfileImageFile($file);
unset($need_images[$key]);
}
}
// For projects with default images, or projects where the custom image
// failed to load, load a builtin image.
if ($need_images) {
$builtin_map = array();
$builtins = array();
foreach ($need_images as $key => $project) {
$icon = $project->getIcon();
$builtin_name = PhabricatorProjectIconSet::getIconImage($icon);
$builtin_name = 'projects/'.$builtin_name;
$builtin = id(new PhabricatorFilesOnDiskBuiltinFile())
->setName($builtin_name);
$builtin_key = $builtin->getBuiltinFileKey();
$builtins[] = $builtin;
$builtin_map[$key] = $builtin_key;
}
$builtin_files = PhabricatorFile::loadBuiltins(
$viewer,
$builtins);
foreach ($need_images as $key => $project) {
$builtin_key = $builtin_map[$key];
$builtin_file = $builtin_files[$builtin_key];
$project->attachProfileImageFile($builtin_file);
}
}
}
$this->loadSlugs($projects);
return $projects;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->status != self::STATUS_ANY) {
switch ($this->status) {
case self::STATUS_OPEN:
case self::STATUS_ACTIVE:
$filter = array(
PhabricatorProjectStatus::STATUS_ACTIVE,
);
break;
case self::STATUS_CLOSED:
case self::STATUS_ARCHIVED:
$filter = array(
PhabricatorProjectStatus::STATUS_ARCHIVED,
);
break;
default:
throw new Exception(
pht(
"Unknown project status '%s'!",
$this->status));
}
$where[] = qsprintf(
$conn,
'project.status IN (%Ld)',
$filter);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'project.status IN (%Ls)',
$this->statuses);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'project.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'project.phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn,
'e.dst IN (%Ls)',
$this->memberPHIDs);
}
if ($this->watcherPHIDs !== null) {
$where[] = qsprintf(
$conn,
'w.dst IN (%Ls)',
$this->watcherPHIDs);
}
if ($this->slugs !== null) {
$where[] = qsprintf(
$conn,
'slug.slug IN (%Ls)',
$this->allSlugs);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn,
'project.name IN (%Ls)',
$this->names);
}
if ($this->namePrefixes) {
$parts = array();
foreach ($this->namePrefixes as $name_prefix) {
$parts[] = qsprintf(
$conn,
'project.name LIKE %>',
$name_prefix);
}
$where[] = qsprintf($conn, '%LO', $parts);
}
if ($this->icons !== null) {
$where[] = qsprintf(
$conn,
'project.icon IN (%Ls)',
$this->icons);
}
if ($this->colors !== null) {
$where[] = qsprintf(
$conn,
'project.color IN (%Ls)',
$this->colors);
}
if ($this->parentPHIDs !== null) {
$where[] = qsprintf(
$conn,
'project.parentProjectPHID IN (%Ls)',
$this->parentPHIDs);
}
if ($this->ancestorPHIDs !== null) {
$ancestor_paths = queryfx_all(
$conn,
'SELECT projectPath, projectDepth FROM %T WHERE phid IN (%Ls)',
id(new PhabricatorProject())->getTableName(),
$this->ancestorPHIDs);
if (!$ancestor_paths) {
throw new PhabricatorEmptyQueryException();
}
$sql = array();
foreach ($ancestor_paths as $ancestor_path) {
$sql[] = qsprintf(
$conn,
'(project.projectPath LIKE %> AND project.projectDepth > %d)',
$ancestor_path['projectPath'],
$ancestor_path['projectDepth']);
}
$where[] = qsprintf($conn, '%LO', $sql);
$where[] = qsprintf(
$conn,
'project.parentProjectPHID IS NOT NULL');
}
if ($this->isMilestone !== null) {
if ($this->isMilestone) {
$where[] = qsprintf(
$conn,
'project.milestoneNumber IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'project.milestoneNumber IS NULL');
}
}
if ($this->hasSubprojects !== null) {
$where[] = qsprintf(
$conn,
'project.hasSubprojects = %d',
(int)$this->hasSubprojects);
}
if ($this->minDepth !== null) {
$where[] = qsprintf(
$conn,
'project.projectDepth >= %d',
$this->minDepth);
}
if ($this->maxDepth !== null) {
$where[] = qsprintf(
$conn,
'project.projectDepth <= %d',
$this->maxDepth);
}
if ($this->minMilestoneNumber !== null) {
$where[] = qsprintf(
$conn,
'project.milestoneNumber >= %d',
$this->minMilestoneNumber);
}
if ($this->maxMilestoneNumber !== null) {
$where[] = qsprintf(
$conn,
'project.milestoneNumber <= %d',
$this->maxMilestoneNumber);
}
if ($this->subtypes !== null) {
$where[] = qsprintf(
$conn,
'project.subtype IN (%Ls)',
$this->subtypes);
}
return $where;
}
protected function shouldGroupQueryResultRows() {
if ($this->memberPHIDs || $this->watcherPHIDs || $this->nameTokens) {
return true;
}
if ($this->slugs) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T e ON e.src = project.phid AND e.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectMaterializedMemberEdgeType::EDGECONST);
}
if ($this->watcherPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T w ON w.src = project.phid AND w.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasWatcherEdgeType::EDGECONST);
}
if ($this->slugs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T slug on slug.projectPHID = project.phid',
id(new PhabricatorProjectSlug())->getTableName());
}
if ($this->nameTokens !== null) {
$name_tokens = $this->getNameTokensForQuery($this->nameTokens);
foreach ($name_tokens as $key => $token) {
$token_table = 'token_'.$key;
$joins[] = qsprintf(
$conn,
'JOIN %T %T ON %T.projectID = project.id AND %T.token LIKE %>',
PhabricatorProject::TABLE_DATASOURCE_TOKEN,
$token_table,
$token_table,
$token_table,
$token);
}
}
return $joins;
}
public function getQueryApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function getPrimaryTableAlias() {
return 'project';
}
private function linkProjectGraph(array $projects, array $ancestors) {
$ancestor_map = mpull($ancestors, null, 'getPHID');
$projects_map = mpull($projects, null, 'getPHID');
$all_map = $projects_map + $ancestor_map;
$done = array();
foreach ($projects as $key => $project) {
$seen = array($project->getPHID() => true);
if (!$this->linkProject($project, $all_map, $done, $seen)) {
$this->didRejectResult($project);
unset($projects[$key]);
continue;
}
foreach ($project->getAncestorProjects() as $ancestor) {
$seen[$ancestor->getPHID()] = true;
}
}
return $projects;
}
private function linkProject($project, array $all, array $done, array $seen) {
$parent_phid = $project->getParentProjectPHID();
// This project has no parent, so just attach `null` and return.
if (!$parent_phid) {
$project->attachParentProject(null);
return true;
}
// This project has a parent, but it failed to load.
if (empty($all[$parent_phid])) {
return false;
}
// Test for graph cycles. If we encounter one, we're going to hide the
// entire cycle since we can't meaningfully resolve it.
if (isset($seen[$parent_phid])) {
return false;
}
$seen[$parent_phid] = true;
$parent = $all[$parent_phid];
$project->attachParentProject($parent);
if (!empty($done[$parent_phid])) {
return true;
}
return $this->linkProject($parent, $all, $done, $seen);
}
private function getAllReachableAncestors(array $projects) {
$ancestors = array();
$seen = mpull($projects, null, 'getPHID');
$stack = $projects;
while ($stack) {
$project = array_pop($stack);
$phid = $project->getPHID();
$ancestors[$phid] = $project;
$parent_phid = $project->getParentProjectPHID();
if (!$parent_phid) {
continue;
}
if (isset($seen[$parent_phid])) {
continue;
}
$seen[$parent_phid] = true;
$stack[] = $project->getParentProject();
}
return $ancestors;
}
private function loadSlugs(array $projects) {
// Build a map from primary slugs to projects.
$primary_map = array();
foreach ($projects as $project) {
$primary_slug = $project->getPrimarySlug();
if ($primary_slug === null) {
continue;
}
$primary_map[$primary_slug] = $project;
}
// Link up all of the queried slugs which correspond to primary
// slugs. If we can link up everything from this (no slugs were queried,
// or only primary slugs were queried) we don't need to load anything
// else.
$unknown = $this->slugNormals;
foreach ($unknown as $input => $normal) {
if (isset($primary_map[$input])) {
$match = $input;
} else if (isset($primary_map[$normal])) {
$match = $normal;
} else {
continue;
}
$this->slugMap[$input] = array(
'slug' => $match,
'projectPHID' => $primary_map[$match]->getPHID(),
);
unset($unknown[$input]);
}
// If we need slugs, we have to load everything.
// If we still have some queried slugs which we haven't mapped, we only
// need to look for them.
// If we've mapped everything, we don't have to do any work.
$project_phids = mpull($projects, 'getPHID');
if ($this->needSlugs) {
$slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
'projectPHID IN (%Ls)',
$project_phids);
} else if ($unknown) {
$slugs = id(new PhabricatorProjectSlug())->loadAllWhere(
'projectPHID IN (%Ls) AND slug IN (%Ls)',
$project_phids,
$unknown);
} else {
$slugs = array();
}
// Link up any slugs we were not able to link up earlier.
$extra_map = mpull($slugs, 'getProjectPHID', 'getSlug');
foreach ($unknown as $input => $normal) {
if (isset($extra_map[$input])) {
$match = $input;
} else if (isset($extra_map[$normal])) {
$match = $normal;
} else {
continue;
}
$this->slugMap[$input] = array(
'slug' => $match,
'projectPHID' => $extra_map[$match],
);
unset($unknown[$input]);
}
if ($this->needSlugs) {
$slug_groups = mgroup($slugs, 'getProjectPHID');
foreach ($projects as $project) {
$project_slugs = idx($slug_groups, $project->getPHID(), array());
$project->attachSlugs($project_slugs);
}
}
}
private function getNameTokensForQuery(array $tokens) {
// When querying for projects by name, only actually search for the five
// longest tokens. MySQL can get grumpy with a large number of JOINs
// with LIKEs and queries for more than 5 tokens are essentially never
// legitimate searches for projects, but users copy/pasting nonsense.
// See also PHI47.
$length_map = array();
foreach ($tokens as $token) {
$length_map[$token] = strlen($token);
}
arsort($length_map);
$length_map = array_slice($length_map, 0, 5, true);
return array_keys($length_map);
}
}
diff --git a/src/applications/project/query/PhabricatorProjectSearchEngine.php b/src/applications/project/query/PhabricatorProjectSearchEngine.php
index cb179c995f..936264a285 100644
--- a/src/applications/project/query/PhabricatorProjectSearchEngine.php
+++ b/src/applications/project/query/PhabricatorProjectSearchEngine.php
@@ -1,359 +1,359 @@
<?php
final class PhabricatorProjectSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Projects');
}
public function getApplicationClassName() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function newQuery() {
return id(new PhabricatorProjectQuery())
->needImages(true)
->needMembers(true)
->needWatchers(true);
}
protected function buildCustomSearchFields() {
$subtype_map = id(new PhabricatorProject())->newEditEngineSubtypeMap();
$hide_subtypes = ($subtype_map->getCount() == 1);
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name'))
->setKey('name')
->setDescription(
pht(
'(Deprecated.) Search for projects with a given name or '.
'hashtag using tokenizer/datasource query matching rules. This '.
'is deprecated in favor of the more powerful "query" '.
'constraint.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Slugs'))
->setIsHidden(true)
->setKey('slugs')
->setDescription(
pht(
'Search for projects with particular slugs. (Slugs are the same '.
'as project hashtags.)')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Members'))
->setKey('memberPHIDs')
->setConduitKey('members')
->setAliases(array('member', 'members')),
id(new PhabricatorUsersSearchField())
->setLabel(pht('Watchers'))
->setKey('watcherPHIDs')
->setConduitKey('watchers')
->setAliases(array('watcher', 'watchers')),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Status'))
->setKey('status')
->setOptions($this->getStatusOptions()),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Milestones'))
->setKey('isMilestone')
->setOptions(
pht('(Show All)'),
pht('Show Only Milestones'),
pht('Hide Milestones'))
->setDescription(
pht(
'Pass true to find only milestones, or false to omit '.
'milestones.')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Root Projects'))
->setKey('isRoot')
->setOptions(
pht('(Show All)'),
pht('Show Only Root Projects'),
pht('Hide Root Projects'))
->setDescription(
pht(
'Pass true to find only root projects, or false to omit '.
'root projects.')),
id(new PhabricatorSearchIntField())
->setLabel(pht('Minimum Depth'))
->setKey('minDepth')
->setIsHidden(true)
->setDescription(
pht(
'Find projects with a given minimum depth. Root projects '.
'have depth 0, their immediate children have depth 1, and '.
'so on.')),
id(new PhabricatorSearchIntField())
->setLabel(pht('Maximum Depth'))
->setKey('maxDepth')
->setIsHidden(true)
->setDescription(
pht(
'Find projects with a given maximum depth. Root projects '.
'have depth 0, their immediate children have depth 1, and '.
'so on.')),
id(new PhabricatorSearchDatasourceField())
->setLabel(pht('Subtypes'))
->setKey('subtypes')
->setAliases(array('subtype'))
->setDescription(
pht('Search for projects with given subtypes.'))
->setDatasource(new PhabricatorProjectSubtypeDatasource())
->setIsHidden($hide_subtypes),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Icons'))
->setKey('icons')
->setOptions($this->getIconOptions()),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Colors'))
->setKey('colors')
->setOptions($this->getColorOptions()),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Parent Projects'))
->setKey('parentPHIDs')
->setConduitKey('parents')
->setAliases(array('parent', 'parents', 'parentPHID'))
->setDescription(pht('Find direct subprojects of specified parents.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Ancestor Projects'))
->setKey('ancestorPHIDs')
->setConduitKey('ancestors')
->setAliases(array('ancestor', 'ancestors', 'ancestorPHID'))
->setDescription(
pht('Find all subprojects beneath specified ancestors.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if (strlen($map['name'])) {
$tokens = PhabricatorTypeaheadDatasource::tokenizeString($map['name']);
$query->withNameTokens($tokens);
}
if ($map['slugs']) {
$query->withSlugs($map['slugs']);
}
if ($map['memberPHIDs']) {
$query->withMemberPHIDs($map['memberPHIDs']);
}
if ($map['watcherPHIDs']) {
$query->withWatcherPHIDs($map['watcherPHIDs']);
}
if ($map['status']) {
$status = idx($this->getStatusValues(), $map['status']);
if ($status) {
$query->withStatus($status);
}
}
if ($map['icons']) {
$query->withIcons($map['icons']);
}
if ($map['colors']) {
$query->withColors($map['colors']);
}
if ($map['isMilestone'] !== null) {
$query->withIsMilestone($map['isMilestone']);
}
$min_depth = $map['minDepth'];
$max_depth = $map['maxDepth'];
if ($min_depth !== null || $max_depth !== null) {
if ($min_depth !== null && $max_depth !== null) {
if ($min_depth > $max_depth) {
throw new Exception(
pht(
'Search constraint "minDepth" must be no larger than '.
'search constraint "maxDepth".'));
}
}
}
if ($map['isRoot'] !== null) {
if ($map['isRoot']) {
if ($max_depth === null) {
$max_depth = 0;
} else {
$max_depth = min(0, $max_depth);
}
$query->withDepthBetween(null, 0);
} else {
if ($min_depth === null) {
$min_depth = 1;
} else {
$min_depth = max($min_depth, 1);
}
}
}
if ($min_depth !== null || $max_depth !== null) {
$query->withDepthBetween($min_depth, $max_depth);
}
if ($map['parentPHIDs']) {
$query->withParentProjectPHIDs($map['parentPHIDs']);
}
if ($map['ancestorPHIDs']) {
$query->withAncestorProjectPHIDs($map['ancestorPHIDs']);
}
if ($map['subtypes']) {
$query->withSubtypes($map['subtypes']);
}
return $query;
}
protected function getURI($path) {
return '/project/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['joined'] = pht('Joined');
}
if ($this->requireViewer()->isLoggedIn()) {
$names['watching'] = pht('Watching');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
// By default, do not show milestones in the list view.
$query->setParameter('isMilestone', false);
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query
->setParameter('status', 'active');
case 'joined':
return $query
->setParameter('memberPHIDs', array($viewer_phid))
->setParameter('status', 'active');
case 'watching':
return $query
->setParameter('watcherPHIDs', array($viewer_phid))
->setParameter('status', 'active');
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
'active' => pht('Show Only Active Projects'),
'archived' => pht('Show Only Archived Projects'),
'all' => pht('Show All Projects'),
);
}
private function getStatusValues() {
return array(
'active' => PhabricatorProjectQuery::STATUS_ACTIVE,
'archived' => PhabricatorProjectQuery::STATUS_ARCHIVED,
'all' => PhabricatorProjectQuery::STATUS_ANY,
);
}
private function getIconOptions() {
$options = array();
$set = new PhabricatorProjectIconSet();
foreach ($set->getIcons() as $icon) {
if ($icon->getIsDisabled()) {
continue;
}
$options[$icon->getKey()] = array(
id(new PHUIIconView())
->setIcon($icon->getIcon()),
' ',
$icon->getLabel(),
);
}
return $options;
}
private function getColorOptions() {
$options = array();
foreach (PhabricatorProjectIconSet::getColorMap() as $color => $name) {
$options[$color] = array(
id(new PHUITagView())
->setType(PHUITagView::TYPE_SHADE)
->setColor($color)
->setName($name),
);
}
return $options;
}
protected function renderResultList(
array $projects,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($projects, 'PhabricatorProject');
$viewer = $this->requireViewer();
$list = id(new PhabricatorProjectListView())
->setUser($viewer)
->setProjects($projects)
->setShowWatching(true)
->setShowMember(true)
->renderList();
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No projects found.'));
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Project'))
->setHref('/project/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Projects are flexible storage containers used as '.
'tags, teams, projects, or anything you need to group.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/project/query/PhabricatorProjectTriggerQuery.php b/src/applications/project/query/PhabricatorProjectTriggerQuery.php
index 306fcb50fe..4f5f6d997c 100644
--- a/src/applications/project/query/PhabricatorProjectTriggerQuery.php
+++ b/src/applications/project/query/PhabricatorProjectTriggerQuery.php
@@ -1,131 +1,131 @@
<?php
final class PhabricatorProjectTriggerQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $activeColumnMin;
private $activeColumnMax;
private $needUsage;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function needUsage($need_usage) {
$this->needUsage = $need_usage;
return $this;
}
public function withActiveColumnCountBetween($min, $max) {
$this->activeColumnMin = $min;
$this->activeColumnMax = $max;
return $this;
}
public function newResultObject() {
return new PhabricatorProjectTrigger();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'trigger.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'trigger.phid IN (%Ls)',
$this->phids);
}
if ($this->activeColumnMin !== null) {
$where[] = qsprintf(
$conn,
'trigger_usage.activeColumnCount >= %d',
$this->activeColumnMin);
}
if ($this->activeColumnMax !== null) {
$where[] = qsprintf(
$conn,
'trigger_usage.activeColumnCount <= %d',
$this->activeColumnMax);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinUsageTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %R trigger_usage ON trigger.phid = trigger_usage.triggerPHID',
new PhabricatorProjectTriggerUsage());
}
return $joins;
}
private function shouldJoinUsageTable() {
if ($this->activeColumnMin !== null) {
return true;
}
if ($this->activeColumnMax !== null) {
return true;
}
return false;
}
protected function didFilterPage(array $triggers) {
if ($this->needUsage) {
$usage_map = id(new PhabricatorProjectTriggerUsage())->loadAllWhere(
'triggerPHID IN (%Ls)',
mpull($triggers, 'getPHID'));
$usage_map = mpull($usage_map, null, 'getTriggerPHID');
foreach ($triggers as $trigger) {
$trigger_phid = $trigger->getPHID();
$usage = idx($usage_map, $trigger_phid);
if (!$usage) {
$usage = id(new PhabricatorProjectTriggerUsage())
->setTriggerPHID($trigger_phid)
->setExamplePHID(null)
->setColumnCount(0)
->setActiveColumnCount(0);
}
$trigger->attachUsage($usage);
}
}
return $triggers;
}
public function getQueryApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
protected function getPrimaryTableAlias() {
return 'trigger';
}
}
diff --git a/src/applications/project/query/PhabricatorProjectTriggerSearchEngine.php b/src/applications/project/query/PhabricatorProjectTriggerSearchEngine.php
index a178ed3e6c..1239dbeade 100644
--- a/src/applications/project/query/PhabricatorProjectTriggerSearchEngine.php
+++ b/src/applications/project/query/PhabricatorProjectTriggerSearchEngine.php
@@ -1,155 +1,155 @@
<?php
final class PhabricatorProjectTriggerSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Triggers');
}
public function getApplicationClassName() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function newQuery() {
return id(new PhabricatorProjectTriggerQuery())
->needUsage(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Active'))
->setKey('isActive')
->setOptions(
pht('(Show All)'),
pht('Show Only Active Triggers'),
pht('Show Only Inactive Triggers')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['isActive'] !== null) {
if ($map['isActive']) {
$query->withActiveColumnCountBetween(1, null);
} else {
$query->withActiveColumnCountBetween(null, 0);
}
}
return $query;
}
protected function getURI($path) {
return '/project/trigger/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['active'] = pht('Active Triggers');
$names['all'] = pht('All Triggers');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter('isActive', true);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $triggers,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($triggers, 'PhabricatorProjectTrigger');
$viewer = $this->requireViewer();
$example_phids = array();
foreach ($triggers as $trigger) {
$example_phid = $trigger->getUsage()->getExamplePHID();
if ($example_phid) {
$example_phids[] = $example_phid;
}
}
$handles = $viewer->loadHandles($example_phids);
$list = id(new PHUIObjectItemListView())
->setViewer($viewer);
foreach ($triggers as $trigger) {
$usage = $trigger->getUsage();
$column_handle = null;
$have_column = false;
$example_phid = $usage->getExamplePHID();
if ($example_phid) {
$column_handle = $handles[$example_phid];
if ($column_handle->isComplete()) {
if (!$column_handle->getPolicyFiltered()) {
$have_column = true;
}
}
}
$column_count = $usage->getColumnCount();
$active_count = $usage->getActiveColumnCount();
if ($have_column) {
if ($active_count > 1) {
$usage_description = pht(
'Used on %s and %s other active column(s).',
$column_handle->renderLink(),
new PhutilNumber($active_count - 1));
} else if ($column_count > 1) {
$usage_description = pht(
'Used on %s and %s other column(s).',
$column_handle->renderLink(),
new PhutilNumber($column_count - 1));
} else {
$usage_description = pht(
'Used on %s.',
$column_handle->renderLink());
}
} else {
if ($active_count) {
$usage_description = pht(
'Used on %s active column(s).',
new PhutilNumber($active_count));
} else if ($column_count) {
$usage_description = pht(
'Used on %s column(s).',
new PhutilNumber($column_count));
} else {
$usage_description = pht(
'Unused trigger.');
}
}
$item = id(new PHUIObjectItemView())
->setObjectName($trigger->getObjectName())
->setHeader($trigger->getDisplayName())
->setHref($trigger->getURI())
->addAttribute($usage_description)
->setDisabled(!$active_count);
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list)
->setNoDataString(pht('No triggers found.'));
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectDatasource.php b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
index 86478a5e1e..acb6999018 100644
--- a/src/applications/project/typeahead/PhabricatorProjectDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectDatasource.php
@@ -1,159 +1,159 @@
<?php
final class PhabricatorProjectDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Projects');
}
public function getPlaceholderText() {
return pht('Type a project name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function loadResults() {
$viewer = $this->getViewer();
$raw_query = $this->getRawQuery();
// Allow users to type "#qa" or "qa" to find "Quality Assurance".
if ($raw_query !== null) {
$raw_query = ltrim($raw_query, '#');
}
$tokens = self::tokenizeString($raw_query);
$query = id(new PhabricatorProjectQuery())
->needImages(true)
->needSlugs(true)
->setOrderVector(array('-status', 'id'));
if ($this->getPhase() == self::PHASE_PREFIX) {
$prefix = $this->getPrefixQuery();
$query->withNamePrefixes(array($prefix));
} else if ($tokens) {
$query->withNameTokens($tokens);
}
// If this is for policy selection, prevent users from using milestones.
$for_policy = $this->getParameter('policy');
if ($for_policy) {
$query->withIsMilestone(false);
}
$for_autocomplete = $this->getParameter('autocomplete');
$projs = $this->executeQuery($query);
$projs = mpull($projs, null, 'getPHID');
$must_have_cols = $this->getParameter('mustHaveColumns', false);
if ($must_have_cols) {
$columns = id(new PhabricatorProjectColumnQuery())
->setViewer($viewer)
->withProjectPHIDs(array_keys($projs))
->withIsProxyColumn(false)
->execute();
$has_cols = mgroup($columns, 'getProjectPHID');
} else {
$has_cols = array_fill_keys(array_keys($projs), true);
}
$is_browse = $this->getIsBrowse();
if ($is_browse && $projs) {
// TODO: This is a little ad-hoc, but we don't currently have
// infrastructure for bulk querying custom fields efficiently.
$table = new PhabricatorProjectCustomFieldStorage();
$descriptions = $table->loadAllWhere(
'objectPHID IN (%Ls) AND fieldIndex = %s',
array_keys($projs),
PhabricatorHash::digestForIndex('std:project:internal:description'));
$descriptions = mpull($descriptions, 'getFieldValue', 'getObjectPHID');
} else {
$descriptions = array();
}
$results = array();
foreach ($projs as $proj) {
$phid = $proj->getPHID();
if (!isset($has_cols[$phid])) {
continue;
}
$slug = $proj->getPrimarySlug();
if (!phutil_nonempty_string($slug)) {
foreach ($proj->getSlugs() as $slug_object) {
$slug = $slug_object->getSlug();
if (strlen($slug)) {
break;
}
}
}
// If we're building results for the autocompleter and this project
// doesn't have any usable slugs, don't return it as a result.
if ($for_autocomplete && !strlen($slug)) {
continue;
}
$closed = null;
if ($proj->isArchived()) {
$closed = pht('Archived');
}
$all_strings = array();
// NOTE: We list the project's name first because results will be
// sorted into prefix vs content phases incorrectly if we don't: it
// will look like "Parent (Milestone)" matched "Parent" as a prefix,
// but it did not.
$all_strings[] = $proj->getName();
if ($proj->isMilestone()) {
$all_strings[] = $proj->getParentProject()->getName();
}
foreach ($proj->getSlugs() as $project_slug) {
$all_strings[] = $project_slug->getSlug();
}
$all_strings = implode("\n", $all_strings);
$proj_result = id(new PhabricatorTypeaheadResult())
->setName($all_strings)
->setDisplayName($proj->getDisplayName())
->setDisplayType($proj->getDisplayIconName())
->setURI($proj->getURI())
->setPHID($phid)
->setIcon($proj->getDisplayIconIcon())
->setColor($proj->getColor())
->setPriorityType('proj')
->setClosed($closed);
if (phutil_nonempty_string($slug)) {
$proj_result->setAutocomplete('#'.$slug);
}
$proj_result->setImageURI($proj->getProfileImageURI());
if ($is_browse) {
$proj_result->addAttribute($proj->getDisplayIconName());
$description = idx($descriptions, $phid);
if (phutil_nonempty_string($description)) {
$summary = PhabricatorMarkupEngine::summarizeSentence($description);
$proj_result->addAttribute($summary);
}
}
$results[] = $proj_result;
}
return $results;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php
index 070cb88485..1c7b1ff3fd 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php
@@ -1,95 +1,95 @@
<?php
final class PhabricatorProjectLogicalAncestorDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Projects');
}
public function getPlaceholderText() {
return pht('Type a project name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectDatasource(),
);
}
protected function didEvaluateTokens(array $results) {
$phids = array();
foreach ($results as $result) {
if (!is_string($result)) {
continue;
}
$phids[] = $result;
}
$map = array();
$skip = array();
if ($phids) {
$phids = array_fuse($phids);
$viewer = $this->getViewer();
$all_projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withAncestorProjectPHIDs($phids)
->execute();
foreach ($phids as $phid) {
$map[$phid][] = $phid;
}
foreach ($all_projects as $project) {
$project_phid = $project->getPHID();
$map[$project_phid][] = $project_phid;
foreach ($project->getAncestorProjects() as $ancestor) {
$ancestor_phid = $ancestor->getPHID();
if (isset($phids[$project_phid]) && isset($phids[$ancestor_phid])) {
// This is a descendant of some other project in the query, so
// we don't need to query for that project. This happens if a user
// runs a query for both "Engineering" and "Engineering > Warp
// Drive". We can only ever match the "Warp Drive" results, so
// we do not need to add the weaker "Engineering" constraint.
$skip[$ancestor_phid] = true;
}
$map[$ancestor_phid][] = $project_phid;
}
}
}
foreach ($results as $key => $result) {
if (!is_string($result)) {
continue;
}
if (empty($map[$result])) {
continue;
}
// This constraint is implied by another, stronger constraint.
if (isset($skip[$result])) {
unset($results[$key]);
continue;
}
// If we have duplicates, don't apply the second constraint.
$skip[$result] = true;
$results[$key] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_ANCESTOR,
$map[$result]);
}
return $results;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalDatasource.php
index b7003cb69e..9cd0fa8b06 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalDatasource.php
@@ -1,29 +1,29 @@
<?php
final class PhabricatorProjectLogicalDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Projects');
}
public function getPlaceholderText() {
return pht('Type a project name or function...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectNoProjectsDatasource(),
new PhabricatorProjectLogicalAncestorDatasource(),
new PhabricatorProjectLogicalOrNotDatasource(),
new PhabricatorProjectLogicalViewerDatasource(),
new PhabricatorProjectLogicalOnlyDatasource(),
new PhabricatorProjectLogicalUserDatasource(),
);
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalOnlyDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalOnlyDatasource.php
index fe521fc6d8..4967e1c59d 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalOnlyDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalOnlyDatasource.php
@@ -1,76 +1,76 @@
<?php
final class PhabricatorProjectLogicalOnlyDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Only');
}
public function getPlaceholderText() {
return pht('Type only()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getDatasourceFunctions() {
return array(
'only' => array(
'name' => pht('Only Match Other Constraints'),
'summary' => pht(
'Find results with only the specified tags.'),
'description' => pht(
"This function is used with other tags, and causes the query to ".
"match only results with exactly those tags. For example, to find ".
"tasks tagged only iOS:".
"\n\n".
"> ios, only()".
"\n\n".
"This will omit results with any other project tag."),
),
);
}
public function loadResults() {
$results = array(
$this->renderOnlyFunctionToken(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
$results[] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_ONLY,
null);
return $results;
}
public function renderFunctionTokens(
$function,
array $argv_list) {
$tokens = array();
foreach ($argv_list as $argv) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->renderOnlyFunctionToken());
}
return $tokens;
}
private function renderOnlyFunctionToken() {
return $this->newFunctionResult()
->setName(pht('Only'))
->setPHID('only()')
->setIcon('fa-asterisk')
->setUnique(true)
->addAttribute(
pht('Select only results with exactly the other specified tags.'));
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
index 026c7ed2ee..b3c7c9b68b 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php
@@ -1,169 +1,169 @@
<?php
final class PhabricatorProjectLogicalOrNotDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Projects');
}
public function getPlaceholderText() {
return pht('Type any(<project>) or not(<project>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'any' => array(
'name' => pht('In Any: ...'),
'arguments' => pht('project'),
'summary' => pht('Find results in any of several projects.'),
'description' => pht(
'This function allows you to find results in one of several '.
'projects. Another way to think of this function is that it '.
'allows you to perform an "or" query.'.
"\n\n".
'By default, if you enter several projects, results are returned '.
'only if they belong to all of the projects you enter. That is, '.
'this query will only return results in //both// projects:'.
"\n\n".
'> ios, android'.
"\n\n".
'If you want to find results in any of several projects, you can '.
'use the `any()` function. For example, you can use this query to '.
'find results which are in //either// project:'.
"\n\n".
'> any(ios), any(android)'.
"\n\n".
'You can combine the `any()` function with normal project tokens '.
'to refine results. For example, use this query to find bugs in '.
'//either// iOS or Android:'.
"\n\n".
'> bug, any(ios), any(android)'),
),
'not' => array(
'name' => pht('Not In: ...'),
'arguments' => pht('project'),
'summary' => pht('Find results not in specific projects.'),
'description' => pht(
'This function allows you to find results which are not in '.
'one or more projects. For example, use this query to find '.
'results which are not associated with a specific project:'.
"\n\n".
'> not(vanilla)'.
"\n\n".
'You can exclude multiple projects. This will cause the query '.
'to return only results which are not in any of the excluded '.
'projects:'.
"\n\n".
'> not(vanilla), not(chocolate)'.
"\n\n".
'You can combine this function with other functions to refine '.
'results. For example, use this query to find iOS results which '.
'are not bugs:'.
"\n\n".
'> ios, not(bug)'),
),
);
}
protected function didLoadResults(array $results) {
$function = $this->getCurrentFunction();
$return_any = ($function !== 'not');
$return_not = ($function !== 'any');
$return = array();
foreach ($results as $result) {
$result
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setColor(null)
->resetAttributes()
->addAttribute(pht('Function'));
if ($return_any) {
$return[] = id(clone $result)
->setPHID('any('.$result->getPHID().')')
->setDisplayName(pht('In Any: %s', $result->getDisplayName()))
->setName('any '.$result->getName())
->addAttribute(pht('Include results tagged with this project.'));
}
if ($return_not) {
$return[] = id(clone $result)
->setPHID('not('.$result->getPHID().')')
->setDisplayName(pht('Not In: %s', $result->getDisplayName()))
->setName('not '.$result->getName())
->addAttribute(pht('Exclude results tagged with this project.'));
}
}
return $return;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$operator = array(
'any' => PhabricatorQueryConstraint::OPERATOR_OR,
'not' => PhabricatorQueryConstraint::OPERATOR_NOT,
);
$results = array();
foreach ($phids as $phid) {
$results[] = new PhabricatorQueryConstraint(
$operator[$function],
$phid);
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
$token->setColor(null);
if ($token->isInvalid()) {
if ($function == 'any') {
$token->setValue(pht('In Any: Invalid Project'));
} else {
$token->setValue(pht('Not In: Invalid Project'));
}
} else {
$token
->setIcon('fa-asterisk')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION);
if ($function == 'any') {
$token
->setKey('any('.$token->getKey().')')
->setValue(pht('In Any: %s', $token->getValue()));
} else {
$token
->setKey('not('.$token->getKey().')')
->setValue(pht('Not In: %s', $token->getValue()));
}
}
}
return $tokens;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php
index bc19c12aa3..b0dca85a05 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php
@@ -1,138 +1,138 @@
<?php
final class PhabricatorProjectLogicalUserDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse User Projects');
}
public function getPlaceholderText() {
return pht('Type projects(<user>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorPeopleDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'projects' => array(
'name' => pht('Projects: ...'),
'arguments' => pht('username'),
'summary' => pht("Find results in any of a user's projects."),
'description' => pht(
"This function allows you to find results associated with any ".
"of the projects a specified user is a member of. For example, ".
"this will find results associated with all of the projects ".
"`%s` is a member of:\n\n%s\n\n",
'alincoln',
'> projects(alincoln)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setColor(null)
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-asterisk')
->setPHID('projects('.$result->getPHID().')')
->setDisplayName(pht("User's Projects: %s", $result->getDisplayName()))
->setName('projects '.$result->getName());
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withMemberPHIDs($phids)
->execute();
$results = array();
foreach ($projects as $project) {
$results[] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_OR,
$project->getPHID());
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$phids = $this->resolvePHIDs($phids);
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht("User's Projects: Invalid User"));
} else {
$token
->setIcon('fa-asterisk')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setKey('projects('.$token->getKey().')')
->setValue(pht("User's Projects: %s", $token->getValue()));
}
}
return $tokens;
}
private function resolvePHIDs(array $phids) {
// If we have a function like `projects(alincoln)`, try to resolve the
// username first. This won't happen normally, but can be passed in from
// the query string.
// The user might also give us an invalid username. In this case, we
// preserve it and return it in-place so we get an "invalid" token rendered
// in the UI. This shows the user where the issue is and best represents
// the user's input.
$usernames = array();
foreach ($phids as $key => $phid) {
if (phid_get_type($phid) != PhabricatorPeopleUserPHIDType::TYPECONST) {
$usernames[$key] = $phid;
}
}
if ($usernames) {
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withUsernames($usernames)
->execute();
$users = mpull($users, null, 'getUsername');
foreach ($usernames as $key => $username) {
$user = idx($users, $username);
if ($user) {
$phids[$key] = $user->getPHID();
}
}
}
return $phids;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php b/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php
index 807986457a..9d1a91376a 100644
--- a/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php
@@ -1,103 +1,103 @@
<?php
final class PhabricatorProjectLogicalViewerDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Viewer Projects');
}
public function getPlaceholderText() {
return pht('Type viewerprojects()...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getDatasourceFunctions() {
return array(
'viewerprojects' => array(
'name' => pht("Current Viewer's Projects"),
'summary' => pht(
"Find results in any of the current viewer's projects."),
'description' => pht(
"This function matches results in any of the current viewing ".
"user's projects:".
"\n\n".
"> viewerprojects()".
"\n\n".
"This normally means //your// projects, but if you save a query ".
"using this function and send it to someone else, it will mean ".
"//their// projects when they run it (they become the current ".
"viewer). This can be useful for building dashboard panels."),
),
);
}
public function loadResults() {
if ($this->getViewer()->getPHID()) {
$results = array($this->renderViewerProjectsFunctionToken());
} else {
$results = array();
}
return $this->filterResultsAgainstTokens($results);
}
protected function canEvaluateFunction($function) {
if (!$this->getViewer()->getPHID()) {
return false;
}
return parent::canEvaluateFunction($function);
}
protected function evaluateFunction($function, array $argv_list) {
$viewer = $this->getViewer();
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withMemberPHIDs(array($viewer->getPHID()))
->execute();
$phids = mpull($projects, 'getPHID');
$results = array();
if ($phids) {
foreach ($phids as $phid) {
$results[] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_OR,
$phid);
}
} else {
$results[] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_EMPTY,
null);
}
return $results;
}
public function renderFunctionTokens(
$function,
array $argv_list) {
$tokens = array();
foreach ($argv_list as $argv) {
$tokens[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->renderViewerProjectsFunctionToken());
}
return $tokens;
}
private function renderViewerProjectsFunctionToken() {
return $this->newFunctionResult()
->setName(pht('Current Viewer\'s Projects'))
->setPHID('viewerprojects()')
->setIcon('fa-asterisk')
->setUnique(true)
->addAttribute(pht('Select projects current viewer is a member of.'));
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectMembersDatasource.php b/src/applications/project/typeahead/PhabricatorProjectMembersDatasource.php
index 524ced454d..308352b39c 100644
--- a/src/applications/project/typeahead/PhabricatorProjectMembersDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectMembersDatasource.php
@@ -1,104 +1,104 @@
<?php
final class PhabricatorProjectMembersDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Members');
}
public function getPlaceholderText() {
return pht('Type members(<project>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectDatasource(),
);
}
public function getDatasourceFunctions() {
return array(
'members' => array(
'name' => pht('Members: ...'),
'arguments' => pht('project'),
'summary' => pht('Find results for members of a project.'),
'description' => pht(
'This function allows you to find results for any of the members '.
'of a project:'.
"\n\n".
'> members(frontend)'),
),
);
}
protected function didLoadResults(array $results) {
foreach ($results as $result) {
$result
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setIcon('fa-users')
->setColor(null)
->setPHID('members('.$result->getPHID().')')
->setDisplayName(pht('Members: %s', $result->getDisplayName()))
->setName($result->getName().' members')
->resetAttributes()
->addAttribute(pht('Function'))
->addAttribute(pht('Select project members.'));
}
return $results;
}
protected function evaluateFunction($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->needMembers(true)
->withPHIDs($phids)
->execute();
$results = array();
foreach ($projects as $project) {
foreach ($project->getMemberPHIDs() as $phid) {
$results[$phid] = $phid;
}
}
return array_values($results);
}
public function renderFunctionTokens($function, array $argv_list) {
$phids = array();
foreach ($argv_list as $argv) {
$phids[] = head($argv);
}
$tokens = $this->renderTokens($phids);
foreach ($tokens as $token) {
// Remove any project color on this token.
$token->setColor(null);
if ($token->isInvalid()) {
$token
->setValue(pht('Members: Invalid Project'));
} else {
$token
->setIcon('fa-users')
->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION)
->setKey('members('.$token->getKey().')')
->setValue(pht('Members: %s', $token->getValue()));
}
}
return $tokens;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php b/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
index d3b5e484e9..a3288b390f 100644
--- a/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php
@@ -1,75 +1,75 @@
<?php
final class PhabricatorProjectNoProjectsDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Not Tagged With Any Projects');
}
public function getPlaceholderText() {
return pht('Type "not tagged with any projects"...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getDatasourceFunctions() {
return array(
'null' => array(
'name' => pht('Not Tagged With Any Projects'),
'summary' => pht(
'Find results which are not tagged with any projects.'),
'description' => pht(
"This function matches results which are not tagged with any ".
"projects. It is usually most often used to find objects which ".
"might have slipped through the cracks and not been organized ".
"properly.\n\n%s",
'> null()'),
),
);
}
public function loadResults() {
$results = array(
$this->buildNullResult(),
);
return $this->filterResultsAgainstTokens($results);
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = new PhabricatorQueryConstraint(
PhabricatorQueryConstraint::OPERATOR_NULL,
'empty');
}
return $results;
}
public function renderFunctionTokens($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
$results[] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult(
$this->buildNullResult());
}
return $results;
}
private function buildNullResult() {
$name = pht('Not Tagged With Any Projects');
return $this->newFunctionResult()
->setUnique(true)
->setPHID('null()')
->setIcon('fa-ban')
->setName('null '.$name)
->setDisplayName($name)
->addAttribute(pht('Select results with no tags.'));
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectSubtypeDatasource.php b/src/applications/project/typeahead/PhabricatorProjectSubtypeDatasource.php
index 68de11e630..c688239fbb 100644
--- a/src/applications/project/typeahead/PhabricatorProjectSubtypeDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectSubtypeDatasource.php
@@ -1,45 +1,45 @@
<?php
final class PhabricatorProjectSubtypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Subtypes');
}
public function getPlaceholderText() {
return pht('Type a project subtype name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$subtype_map = id(new PhabricatorProject())->newEditEngineSubtypeMap();
foreach ($subtype_map->getSubtypes() as $key => $subtype) {
$result = id(new PhabricatorTypeaheadResult())
->setIcon($subtype->getIcon())
->setColor($subtype->getColor())
->setPHID($key)
->setName($subtype->getName());
$results[$key] = $result;
}
return $results;
}
}
diff --git a/src/applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php b/src/applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php
index c0e237f0c6..dfd10c051d 100644
--- a/src/applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php
+++ b/src/applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php
@@ -1,36 +1,36 @@
<?php
final class PhabricatorProjectUserFunctionDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse User Projects');
}
public function getPlaceholderText() {
return pht('Type projects(<user>)...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorProjectApplication';
+ return PhabricatorProjectApplication::class;
}
public function getComponentDatasources() {
return array(
new PhabricatorProjectLogicalUserDatasource(),
);
}
protected function evaluateFunction($function, array $argv_list) {
$result = parent::evaluateFunction($function, $argv_list);
foreach ($result as $k => $v) {
if ($v instanceof PhabricatorQueryConstraint) {
$result[$k] = $v->getValue();
}
}
return $result;
}
}
diff --git a/src/applications/repository/editor/PhabricatorRepositoryEditor.php b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
index c23fc41624..19cd02507f 100644
--- a/src/applications/repository/editor/PhabricatorRepositoryEditor.php
+++ b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
@@ -1,91 +1,91 @@
<?php
final class PhabricatorRepositoryEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Repositories');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_EDGE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,
Exception $ex) {
$errors = array();
$errors[] = new PhabricatorApplicationTransactionValidationError(
null,
pht('Invalid'),
pht(
'The chosen callsign or repository short name is already in '.
'use by another repository.'),
null);
throw new PhabricatorApplicationTransactionValidationException($errors);
}
protected function supportsSearch() {
return true;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
// If the repository does not have a local path yet, assign it one based
// on its ID. We can't do this earlier because we won't have an ID yet.
$local_path = $object->getLocalPath();
if (!phutil_nonempty_string($local_path)) {
$local_key = 'repository.default-local-path';
$local_root = PhabricatorEnv::getEnvConfig($local_key);
$local_root = rtrim($local_root, '/');
$id = $object->getID();
$local_path = "{$local_root}/{$id}/";
$object->setLocalPath($local_path);
$object->save();
}
if ($this->getIsNewObject()) {
// The default state of repositories is to be hosted, if they are
// enabled without configuring any "Observe" URIs.
$object->setHosted(true);
$object->save();
// Create this repository's builtin URIs.
$builtin_uris = $object->newBuiltinURIs();
foreach ($builtin_uris as $uri) {
$uri->save();
}
id(new DiffusionRepositoryClusterEngine())
->setViewer($this->getActor())
->setRepository($object)
->synchronizeWorkingCopyAfterCreation();
}
$object->writeStatusMessage(
PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE,
null);
return $xactions;
}
}
diff --git a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
index 9d80d42bb7..8cadee7d52 100644
--- a/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php
@@ -1,92 +1,92 @@
<?php
final class PhabricatorRepositoryIdentityEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'repository.identity';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Repository Identities');
}
public function getSummaryHeader() {
return pht('Edit Repository Identity Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Repository identities.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function newEditableObject() {
return new PhabricatorRepositoryIdentity();
}
protected function newObjectQuery() {
return new PhabricatorRepositoryIdentityQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Identity');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Identity');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Identity: %s', $object->getIdentityShortName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Identity');
}
protected function getObjectCreateShortText() {
return pht('Create Identity');
}
protected function getObjectName() {
return pht('Identity');
}
protected function getEditorURI() {
return '/diffusion/identity/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/diffusion/identity/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
PhabricatorRepositoryIdentityEditViewCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new DiffusionIdentityAssigneeEditField())
->setKey('manuallySetUserPHID')
->setLabel(pht('Assigned To'))
->setDescription(pht('Override this identity\'s assignment.'))
->setTransactionType(
PhabricatorRepositoryIdentityAssignTransaction::TRANSACTIONTYPE)
->setIsCopyable(true)
->setIsNullable(true)
->setSingleValue($object->getManuallySetUserPHID()),
);
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php
index df84f2dcfd..a803de5023 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php
@@ -1,117 +1,117 @@
<?php
final class PhabricatorRepositoryCommitPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'CMIT';
public function getTypeName() {
return pht('Diffusion Commit');
}
public function newObject() {
return new PhabricatorRepositoryCommit();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DiffusionCommitQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$unreachable = array();
foreach ($handles as $phid => $handle) {
$commit = $objects[$phid];
if ($commit->isUnreachable()) {
$unreachable[$phid] = $commit;
}
}
if ($unreachable) {
$query = id(new DiffusionCommitHintQuery())
->setViewer($query->getViewer())
->withCommits($unreachable);
$query->execute();
$hints = $query->getCommitMap();
} else {
$hints = array();
}
foreach ($handles as $phid => $handle) {
$commit = $objects[$phid];
$repository = $commit->getRepository();
$commit_identifier = $commit->getCommitIdentifier();
$name = $repository->formatCommitName($commit_identifier);
if ($commit->isUnreachable()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
// If we have a hint about this commit being rewritten, add the
// rewrite target to the handle name. This reduces the chance users
// will be caught offguard by the rewrite.
$hint = idx($hints, $phid);
if ($hint && $hint->isRewritten()) {
$new_name = $hint->getNewCommitIdentifier();
$new_name = $repository->formatCommitName($new_name);
$name = pht("%s \xE2\x99\xBB %s", $name, $new_name);
}
}
$summary = $commit->getSummary();
if (strlen($summary)) {
$full_name = $name.': '.$summary;
} else {
$full_name = $name;
}
$handle->setName($name);
$handle->setFullName($full_name);
$handle->setURI($commit->getURI());
$handle->setTimestamp($commit->getEpoch());
}
}
public static function getCommitObjectNamePattern() {
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
return
'(?:r[A-Z]+:?|R[0-9]+:)[1-9]\d*'.
'|'.
'(?:r[A-Z]+:?|R[0-9]+:)[a-f0-9]{'.$min_qualified.',40}'.
'|'.
'[a-f0-9]{'.$min_unqualified.',40}';
}
public function canLoadNamedObject($name) {
$pattern = self::getCommitObjectNamePattern();
return preg_match('(^'.$pattern.'$)', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$query = id(new DiffusionCommitQuery())
->setViewer($query->getViewer())
->withIdentifiers($names);
$query->execute();
return $query->getIdentifierMap();
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
index 873cfbbae6..c3844c3ef2 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php
@@ -1,48 +1,48 @@
<?php
final class PhabricatorRepositoryIdentityPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'RIDT';
public function getTypeName() {
return pht('Repository Identity');
}
public function newObject() {
return new PhabricatorRepositoryIdentity();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryIdentityQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$avatar_uri = celerity_get_resource_uri('/rsrc/image/avatar.png');
foreach ($handles as $phid => $handle) {
$identity = $objects[$phid];
$id = $identity->getID();
$name = $identity->getIdentityNameRaw();
$handle->setObjectName(pht('Identity %d', $id));
$handle->setName($name);
$handle->setURI($identity->getURI());
$handle->setIcon('fa-user');
$handle->setImageURI($avatar_uri);
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPullEventPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryPullEventPHIDType.php
index 45ed2819fb..3b0400436d 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPullEventPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPullEventPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorRepositoryPullEventPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PULE';
public function getTypeName() {
return pht('Pull Event');
}
public function newObject() {
return new PhabricatorRepositoryPullEvent();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryPullEventQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$event = $objects[$phid];
$handle->setName(pht('Pull Event %d', $event->getID()));
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php
index 364ce62e5d..65741fded1 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorRepositoryPushEventPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PSHE';
public function getTypeName() {
return pht('Push Event');
}
public function newObject() {
return new PhabricatorRepositoryPushEvent();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryPushEventQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$event = $objects[$phid];
$handle->setName(pht('Push Event %d', $event->getID()));
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php
index 6af117db19..a5dc223ac8 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorRepositoryPushLogPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PSHL';
public function getTypeName() {
return pht('Push Log');
}
public function newObject() {
return new PhabricatorRepositoryPushLog();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryPushLogQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$log = $objects[$phid];
$handle->setName(pht('Push Log %d', $log->getID()));
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryRefCursorPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryRefCursorPHIDType.php
index 30fbc4b6ae..aac22de8ca 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryRefCursorPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryRefCursorPHIDType.php
@@ -1,46 +1,46 @@
<?php
final class PhabricatorRepositoryRefCursorPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'RREF';
public function getTypeName() {
return pht('Repository Ref');
}
public function getTypeIcon() {
return 'fa-code-fork';
}
public function newObject() {
return new PhabricatorRepositoryRefCursor();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryRefCursorQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$ref = $objects[$phid];
$name = $ref->getRefName();
$handle->setName($name);
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php
index 6ca67257cf..dcc0e174e5 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php
@@ -1,89 +1,89 @@
<?php
final class PhabricatorRepositoryRepositoryPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'REPO';
public function getTypeName() {
return pht('Repository');
}
public function getTypeIcon() {
return 'fa-code';
}
public function newObject() {
return new PhabricatorRepository();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$repository = $objects[$phid];
$monogram = $repository->getMonogram();
$name = $repository->getName();
$uri = $repository->getURI();
$handle
->setName($monogram)
->setFullName("{$monogram} {$name}")
->setURI($uri)
->setMailStampName($monogram);
if ($repository->getStatus() !== PhabricatorRepository::STATUS_ACTIVE) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^(r[A-Z]+|R[1-9]\d*)\z/', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$results = array();
$id_map = array();
foreach ($names as $key => $name) {
$id = substr($name, 1);
$id_map[$id][] = $name;
$names[$key] = substr($name, 1);
}
$query = id(new PhabricatorRepositoryQuery())
->setViewer($query->getViewer())
->withIdentifiers($names);
if ($query->execute()) {
$objects = $query->getIdentifierMap();
foreach ($objects as $key => $object) {
foreach (idx($id_map, $key, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
} else {
return array();
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php b/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php
index ade9560a93..86a3a6d0f9 100644
--- a/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorRepositorySyncEventPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'SYNE';
public function getTypeName() {
return pht('Sync Event');
}
public function newObject() {
return new PhabricatorRepositorySyncEvent();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositorySyncEventQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$event = $objects[$phid];
$handle->setName(pht('Sync Event %d', $event->getID()));
}
}
}
diff --git a/src/applications/repository/phid/PhabricatorRepositoryURIPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryURIPHIDType.php
index 658b942418..b330631c55 100644
--- a/src/applications/repository/phid/PhabricatorRepositoryURIPHIDType.php
+++ b/src/applications/repository/phid/PhabricatorRepositoryURIPHIDType.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorRepositoryURIPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'RURI';
public function getTypeName() {
return pht('Repository URI');
}
public function newObject() {
return new PhabricatorRepositoryURI();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryURIQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$uri = $objects[$phid];
$handle->setName(
pht('URI %d %s', $uri->getID(), $uri->getDisplayURI()));
}
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php b/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
index 08f0ada159..976aef9ab4 100644
--- a/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php
@@ -1,60 +1,60 @@
<?php
final class PhabricatorRepositoryGitLFSRefQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $repositoryPHIDs;
private $objectHashes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withObjectHashes(array $hashes) {
$this->objectHashes = $hashes;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryGitLFSRef();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->objectHashes !== null) {
$where[] = qsprintf(
$conn,
'objectHash IN (%Ls)',
$this->objectHashes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
index 2b05b542d5..78fd4f729d 100644
--- a/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryIdentityQuery.php
@@ -1,156 +1,156 @@
<?php
final class PhabricatorRepositoryIdentityQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $identityNames;
private $emailAddresses;
private $assignedPHIDs;
private $effectivePHIDs;
private $identityNameLike;
private $hasEffectivePHID;
private $relatedPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withIdentityNames(array $names) {
$this->identityNames = $names;
return $this;
}
public function withIdentityNameLike($name_like) {
$this->identityNameLike = $name_like;
return $this;
}
public function withEmailAddresses(array $addresses) {
$this->emailAddresses = $addresses;
return $this;
}
public function withAssignedPHIDs(array $assigned) {
$this->assignedPHIDs = $assigned;
return $this;
}
public function withEffectivePHIDs(array $effective) {
$this->effectivePHIDs = $effective;
return $this;
}
public function withRelatedPHIDs(array $related) {
$this->relatedPHIDs = $related;
return $this;
}
public function withHasEffectivePHID($has_effective_phid) {
$this->hasEffectivePHID = $has_effective_phid;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryIdentity();
}
protected function getPrimaryTableAlias() {
return 'identity';
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'identity.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'identity.phid IN (%Ls)',
$this->phids);
}
if ($this->assignedPHIDs !== null) {
$where[] = qsprintf(
$conn,
'identity.manuallySetUserPHID IN (%Ls)',
$this->assignedPHIDs);
}
if ($this->effectivePHIDs !== null) {
$where[] = qsprintf(
$conn,
'identity.currentEffectiveUserPHID IN (%Ls)',
$this->effectivePHIDs);
}
if ($this->hasEffectivePHID !== null) {
if ($this->hasEffectivePHID) {
$where[] = qsprintf(
$conn,
'identity.currentEffectiveUserPHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'identity.currentEffectiveUserPHID IS NULL');
}
}
if ($this->identityNames !== null) {
$name_hashes = array();
foreach ($this->identityNames as $name) {
$name_hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn,
'identity.identityNameHash IN (%Ls)',
$name_hashes);
}
if ($this->emailAddresses !== null) {
$where[] = qsprintf(
$conn,
'identity.emailAddress IN (%Ls)',
$this->emailAddresses);
}
if ($this->identityNameLike != null) {
$where[] = qsprintf(
$conn,
'identity.identityNameRaw LIKE %~',
$this->identityNameLike);
}
if ($this->relatedPHIDs !== null) {
$where[] = qsprintf(
$conn,
'(identity.manuallySetUserPHID IN (%Ls) OR
identity.currentEffectiveUserPHID IN (%Ls) OR
identity.automaticGuessedUserPHID IN (%Ls))',
$this->relatedPHIDs,
$this->relatedPHIDs,
$this->relatedPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php b/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
index 8d4f14e0ce..b398012173 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPullEventQuery.php
@@ -1,131 +1,131 @@
<?php
final class PhabricatorRepositoryPullEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $pullerPHIDs;
private $epochMin;
private $epochMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withPullerPHIDs(array $puller_phids) {
$this->pullerPHIDs = $puller_phids;
return $this;
}
public function withEpochBetween($min, $max) {
$this->epochMin = $min;
$this->epochMax = $max;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryPullEvent();
}
protected function willFilterPage(array $events) {
// If a pull targets an invalid repository or fails before authenticating,
// it may not have an associated repository.
$repository_phids = mpull($events, 'getRepositoryPHID');
$repository_phids = array_filter($repository_phids);
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
} else {
$repositories = array();
}
foreach ($events as $key => $event) {
$phid = $event->getRepositoryPHID();
if (!$phid) {
$event->attachRepository(null);
continue;
}
if (empty($repositories[$phid])) {
unset($events[$key]);
$this->didRejectResult($event);
continue;
}
$event->attachRepository($repositories[$phid]);
}
return $events;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->pullerPHIDs !== null) {
$where[] = qsprintf(
$conn,
'pullerPHID in (%Ls)',
$this->pullerPHIDs);
}
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'epoch >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'epoch <= %d',
$this->epochMax);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
index d1ce937b86..eec40da96d 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
@@ -1,118 +1,118 @@
<?php
final class PhabricatorRepositoryPushEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $pusherPHIDs;
private $needLogs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withPusherPHIDs(array $pusher_phids) {
$this->pusherPHIDs = $pusher_phids;
return $this;
}
public function needLogs($need_logs) {
$this->needLogs = $need_logs;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryPushEvent();
}
protected function willFilterPage(array $events) {
$repository_phids = mpull($events, 'getRepositoryPHID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($events as $key => $event) {
$phid = $event->getRepositoryPHID();
if (empty($repositories[$phid])) {
unset($events[$key]);
continue;
}
$event->attachRepository($repositories[$phid]);
}
return $events;
}
protected function didFilterPage(array $events) {
$phids = mpull($events, 'getPHID');
if ($this->needLogs) {
$logs = id(new PhabricatorRepositoryPushLogQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPushEventPHIDs($phids)
->execute();
$logs = mgroup($logs, 'getPushEventPHID');
foreach ($events as $key => $event) {
$event_logs = idx($logs, $event->getPHID(), array());
$event->attachLogs($event_logs);
}
}
return $events;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->pusherPHIDs !== null) {
$where[] = qsprintf(
$conn,
'pusherPHID in (%Ls)',
$this->pusherPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
index 16897a1e4b..2f264510b2 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
@@ -1,195 +1,195 @@
<?php
final class PhabricatorRepositoryPushLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $pusherPHIDs;
private $refTypes;
private $newRefs;
private $pushEventPHIDs;
private $epochMin;
private $epochMax;
private $blockingHeraldRulePHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withPusherPHIDs(array $pusher_phids) {
$this->pusherPHIDs = $pusher_phids;
return $this;
}
public function withRefTypes(array $ref_types) {
$this->refTypes = $ref_types;
return $this;
}
public function withNewRefs(array $new_refs) {
$this->newRefs = $new_refs;
return $this;
}
public function withPushEventPHIDs(array $phids) {
$this->pushEventPHIDs = $phids;
return $this;
}
public function withEpochBetween($min, $max) {
$this->epochMin = $min;
$this->epochMax = $max;
return $this;
}
public function withBlockingHeraldRulePHIDs(array $phids) {
$this->blockingHeraldRulePHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryPushLog();
}
protected function willFilterPage(array $logs) {
$event_phids = mpull($logs, 'getPushEventPHID');
$events = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($event_phids)
->execute();
$events = mpull($events, null, 'getPHID');
foreach ($logs as $key => $log) {
$event = idx($events, $log->getPushEventPHID());
if (!$event) {
unset($logs[$key]);
continue;
}
$log->attachPushEvent($event);
}
return $logs;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'log.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'log.phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'log.repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->pusherPHIDs !== null) {
$where[] = qsprintf(
$conn,
'log.pusherPHID in (%Ls)',
$this->pusherPHIDs);
}
if ($this->pushEventPHIDs !== null) {
$where[] = qsprintf(
$conn,
'log.pushEventPHID in (%Ls)',
$this->pushEventPHIDs);
}
if ($this->refTypes !== null) {
$where[] = qsprintf(
$conn,
'log.refType IN (%Ls)',
$this->refTypes);
}
if ($this->newRefs !== null) {
$where[] = qsprintf(
$conn,
'log.refNew IN (%Ls)',
$this->newRefs);
}
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'log.epoch >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'log.epoch <= %d',
$this->epochMax);
}
if ($this->blockingHeraldRulePHIDs !== null) {
$where[] = qsprintf(
$conn,
'(event.rejectCode = %d AND event.rejectDetails IN (%Ls))',
PhabricatorRepositoryPushLog::REJECT_HERALD,
$this->blockingHeraldRulePHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinPushEventTable()) {
$joins[] = qsprintf(
$conn,
'JOIN %T event ON event.phid = log.pushEventPHID',
id(new PhabricatorRepositoryPushEvent())->getTableName());
}
return $joins;
}
private function shouldJoinPushEventTable() {
if ($this->blockingHeraldRulePHIDs !== null) {
return true;
}
return false;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
protected function getPrimaryTableAlias() {
return 'log';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php b/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php
index 271d8a9c14..642b22bc24 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php
@@ -1,273 +1,273 @@
<?php
final class PhabricatorRepositoryPushLogSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Push Logs');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return new PhabricatorRepositoryPushLogQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['repositoryPHIDs']) {
$query->withRepositoryPHIDs($map['repositoryPHIDs']);
}
if ($map['pusherPHIDs']) {
$query->withPusherPHIDs($map['pusherPHIDs']);
}
if ($map['createdStart'] || $map['createdEnd']) {
$query->withEpochBetween(
$map['createdStart'],
$map['createdEnd']);
}
if ($map['blockingHeraldRulePHIDs']) {
$query->withBlockingHeraldRulePHIDs($map['blockingHeraldRulePHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchDatasourceField())
->setDatasource(new DiffusionRepositoryDatasource())
->setKey('repositoryPHIDs')
->setAliases(array('repository', 'repositories', 'repositoryPHID'))
->setLabel(pht('Repositories'))
->setDescription(
pht('Search for push logs for specific repositories.')),
id(new PhabricatorUsersSearchField())
->setKey('pusherPHIDs')
->setAliases(array('pusher', 'pushers', 'pusherPHID'))
->setLabel(pht('Pushers'))
->setDescription(
pht('Search for push logs by specific users.')),
id(new PhabricatorSearchDatasourceField())
->setDatasource(new HeraldRuleDatasource())
->setKey('blockingHeraldRulePHIDs')
->setLabel(pht('Blocked By'))
->setDescription(
pht('Search for pushes blocked by particular Herald rules.')),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created After'))
->setKey('createdStart'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Created Before'))
->setKey('createdEnd'),
);
}
protected function getURI($path) {
return '/diffusion/pushlog/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Push Logs'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $logs,
PhabricatorSavedQuery $query,
array $handles) {
$table = id(new DiffusionPushLogListView())
->setViewer($this->requireViewer())
->setLogs($logs);
return id(new PhabricatorApplicationSearchResultView())
->setTable($table);
}
protected function newExportFields() {
$viewer = $this->requireViewer();
$fields = array(
id(new PhabricatorIDExportField())
->setKey('pushID')
->setLabel(pht('Push ID')),
id(new PhabricatorStringExportField())
->setKey('unique')
->setLabel(pht('Unique')),
id(new PhabricatorStringExportField())
->setKey('protocol')
->setLabel(pht('Protocol')),
id(new PhabricatorPHIDExportField())
->setKey('repositoryPHID')
->setLabel(pht('Repository PHID')),
id(new PhabricatorStringExportField())
->setKey('repository')
->setLabel(pht('Repository')),
id(new PhabricatorPHIDExportField())
->setKey('pusherPHID')
->setLabel(pht('Pusher PHID')),
id(new PhabricatorStringExportField())
->setKey('pusher')
->setLabel(pht('Pusher')),
id(new PhabricatorPHIDExportField())
->setKey('devicePHID')
->setLabel(pht('Device PHID')),
id(new PhabricatorStringExportField())
->setKey('device')
->setLabel(pht('Device')),
id(new PhabricatorStringExportField())
->setKey('type')
->setLabel(pht('Ref Type')),
id(new PhabricatorStringExportField())
->setKey('name')
->setLabel(pht('Ref Name')),
id(new PhabricatorStringExportField())
->setKey('old')
->setLabel(pht('Ref Old')),
id(new PhabricatorStringExportField())
->setKey('new')
->setLabel(pht('Ref New')),
id(new PhabricatorIntExportField())
->setKey('flags')
->setLabel(pht('Flags')),
id(new PhabricatorStringListExportField())
->setKey('flagNames')
->setLabel(pht('Flag Names')),
id(new PhabricatorIntExportField())
->setKey('result')
->setLabel(pht('Result')),
id(new PhabricatorStringExportField())
->setKey('resultName')
->setLabel(pht('Result Name')),
id(new PhabricatorStringExportField())
->setKey('resultDetails')
->setLabel(pht('Result Details')),
id(new PhabricatorIntExportField())
->setKey('hostWait')
->setLabel(pht('Host Wait (us)')),
id(new PhabricatorIntExportField())
->setKey('writeWait')
->setLabel(pht('Write Wait (us)')),
id(new PhabricatorIntExportField())
->setKey('readWait')
->setLabel(pht('Read Wait (us)')),
id(new PhabricatorIntExportField())
->setKey('hookWait')
->setLabel(pht('Hook Wait (us)')),
);
if ($viewer->getIsAdmin()) {
$fields[] = id(new PhabricatorStringExportField())
->setKey('remoteAddress')
->setLabel(pht('Remote Address'));
}
return $fields;
}
protected function newExportData(array $logs) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($logs as $log) {
$phids[] = $log->getPusherPHID();
$phids[] = $log->getDevicePHID();
$phids[] = $log->getPushEvent()->getRepositoryPHID();
}
$handles = $viewer->loadHandles($phids);
$flag_map = PhabricatorRepositoryPushLog::getFlagDisplayNames();
$reject_map = PhabricatorRepositoryPushLog::getRejectCodeDisplayNames();
$export = array();
foreach ($logs as $log) {
$event = $log->getPushEvent();
$repository_phid = $event->getRepositoryPHID();
if ($repository_phid) {
$repository_name = $handles[$repository_phid]->getName();
} else {
$repository_name = null;
}
$pusher_phid = $log->getPusherPHID();
if ($pusher_phid) {
$pusher_name = $handles[$pusher_phid]->getName();
} else {
$pusher_name = null;
}
$device_phid = $log->getDevicePHID();
if ($device_phid) {
$device_name = $handles[$device_phid]->getName();
} else {
$device_name = null;
}
$flags = $log->getChangeFlags();
$flag_names = array();
foreach ($flag_map as $flag_key => $flag_name) {
if (($flags & $flag_key) === $flag_key) {
$flag_names[] = $flag_name;
}
}
$result = $event->getRejectCode();
$result_name = idx($reject_map, $result, pht('Unknown ("%s")', $result));
$map = array(
'pushID' => $event->getID(),
'unique' => $event->getRequestIdentifier(),
'protocol' => $event->getRemoteProtocol(),
'repositoryPHID' => $repository_phid,
'repository' => $repository_name,
'pusherPHID' => $pusher_phid,
'pusher' => $pusher_name,
'devicePHID' => $device_phid,
'device' => $device_name,
'type' => $log->getRefType(),
'name' => $log->getRefName(),
'old' => $log->getRefOld(),
'new' => $log->getRefNew(),
'flags' => $flags,
'flagNames' => $flag_names,
'result' => $result,
'resultName' => $result_name,
'resultDetails' => $event->getRejectDetails(),
'hostWait' => $event->getHostWait(),
'writeWait' => $event->getWriteWait(),
'readWait' => $event->getReadWait(),
'hookWait' => $event->getHookWait(),
);
if ($viewer->getIsAdmin()) {
$map['remoteAddress'] = $event->getRemoteAddress();
}
$export[] = $map;
}
return $export;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php
index 8dead39758..04a99bcf11 100644
--- a/src/applications/repository/query/PhabricatorRepositoryQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php
@@ -1,688 +1,688 @@
<?php
final class PhabricatorRepositoryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $callsigns;
private $types;
private $uuids;
private $uris;
private $slugs;
private $almanacServicePHIDs;
private $numericIdentifiers;
private $callsignIdentifiers;
private $phidIdentifiers;
private $monogramIdentifiers;
private $slugIdentifiers;
private $identifierMap;
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ALL = 'status-all';
private $status = self::STATUS_ALL;
const HOSTED_PHABRICATOR = 'hosted-phab';
const HOSTED_REMOTE = 'hosted-remote';
const HOSTED_ALL = 'hosted-all';
private $hosted = self::HOSTED_ALL;
private $needMostRecentCommits;
private $needCommitCounts;
private $needProjectPHIDs;
private $needURIs;
private $needProfileImage;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCallsigns(array $callsigns) {
$this->callsigns = $callsigns;
return $this;
}
public function withIdentifiers(array $identifiers) {
$identifiers = array_fuse($identifiers);
$ids = array();
$callsigns = array();
$phids = array();
$monograms = array();
$slugs = array();
foreach ($identifiers as $identifier) {
if ($identifier === null) {
continue;
}
if (ctype_digit((string)$identifier)) {
$ids[$identifier] = $identifier;
continue;
}
if (preg_match('/^(r[A-Z]+|R[1-9]\d*)\z/', $identifier)) {
$monograms[$identifier] = $identifier;
continue;
}
$repository_type = PhabricatorRepositoryRepositoryPHIDType::TYPECONST;
if (phid_get_type($identifier) === $repository_type) {
$phids[$identifier] = $identifier;
continue;
}
if (preg_match('/^[A-Z]+\z/', $identifier)) {
$callsigns[$identifier] = $identifier;
continue;
}
$slugs[$identifier] = $identifier;
}
$this->numericIdentifiers = $ids;
$this->callsignIdentifiers = $callsigns;
$this->phidIdentifiers = $phids;
$this->monogramIdentifiers = $monograms;
$this->slugIdentifiers = $slugs;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withHosted($hosted) {
$this->hosted = $hosted;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withUUIDs(array $uuids) {
$this->uuids = $uuids;
return $this;
}
public function withURIs(array $uris) {
$this->uris = $uris;
return $this;
}
public function withSlugs(array $slugs) {
$this->slugs = $slugs;
return $this;
}
public function withAlmanacServicePHIDs(array $phids) {
$this->almanacServicePHIDs = $phids;
return $this;
}
public function needCommitCounts($need_counts) {
$this->needCommitCounts = $need_counts;
return $this;
}
public function needMostRecentCommits($need_commits) {
$this->needMostRecentCommits = $need_commits;
return $this;
}
public function needProjectPHIDs($need_phids) {
$this->needProjectPHIDs = $need_phids;
return $this;
}
public function needURIs($need_uris) {
$this->needURIs = $need_uris;
return $this;
}
public function needProfileImage($need) {
$this->needProfileImage = $need;
return $this;
}
public function getBuiltinOrders() {
return array(
'committed' => array(
'vector' => array('committed', 'id'),
'name' => pht('Most Recent Commit'),
),
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Name'),
),
'callsign' => array(
'vector' => array('callsign'),
'name' => pht('Callsign'),
),
'size' => array(
'vector' => array('size', 'id'),
'name' => pht('Size'),
),
) + parent::getBuiltinOrders();
}
public function getIdentifierMap() {
if ($this->identifierMap === null) {
throw new PhutilInvalidStateException('execute');
}
return $this->identifierMap;
}
protected function willExecute() {
$this->identifierMap = array();
}
public function newResultObject() {
return new PhabricatorRepository();
}
protected function loadPage() {
$table = $this->newResultObject();
$data = $this->loadStandardPageRows($table);
$repositories = $table->loadAllFromArray($data);
if ($this->needCommitCounts) {
$sizes = ipull($data, 'size', 'id');
foreach ($repositories as $id => $repository) {
$repository->attachCommitCount(nonempty($sizes[$id], 0));
}
}
if ($this->needMostRecentCommits) {
$commit_ids = ipull($data, 'lastCommitID', 'id');
$commit_ids = array_filter($commit_ids);
if ($commit_ids) {
$commits = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->withIDs($commit_ids)
->needCommitData(true)
->needIdentities(true)
->execute();
} else {
$commits = array();
}
foreach ($repositories as $id => $repository) {
$commit = null;
if (idx($commit_ids, $id)) {
$commit = idx($commits, $commit_ids[$id]);
}
$repository->attachMostRecentCommit($commit);
}
}
return $repositories;
}
protected function willFilterPage(array $repositories) {
assert_instances_of($repositories, 'PhabricatorRepository');
// TODO: Denormalize repository status into the PhabricatorRepository
// table so we can do this filtering in the database.
foreach ($repositories as $key => $repo) {
$status = $this->status;
switch ($status) {
case self::STATUS_OPEN:
if (!$repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_CLOSED:
if ($repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_ALL:
break;
default:
throw new Exception("Unknown status '{$status}'!");
}
// TODO: This should also be denormalized.
$hosted = $this->hosted;
switch ($hosted) {
case self::HOSTED_PHABRICATOR:
if (!$repo->isHosted()) {
unset($repositories[$key]);
}
break;
case self::HOSTED_REMOTE:
if ($repo->isHosted()) {
unset($repositories[$key]);
}
break;
case self::HOSTED_ALL:
break;
default:
throw new Exception(pht("Unknown hosted failed '%s'!", $hosted));
}
}
// Build the identifierMap
if ($this->numericIdentifiers) {
foreach ($this->numericIdentifiers as $id) {
if (isset($repositories[$id])) {
$this->identifierMap[$id] = $repositories[$id];
}
}
}
if ($this->callsignIdentifiers) {
$repository_callsigns = mpull($repositories, null, 'getCallsign');
foreach ($this->callsignIdentifiers as $callsign) {
if (isset($repository_callsigns[$callsign])) {
$this->identifierMap[$callsign] = $repository_callsigns[$callsign];
}
}
}
if ($this->phidIdentifiers) {
$repository_phids = mpull($repositories, null, 'getPHID');
foreach ($this->phidIdentifiers as $phid) {
if (isset($repository_phids[$phid])) {
$this->identifierMap[$phid] = $repository_phids[$phid];
}
}
}
if ($this->monogramIdentifiers) {
$monogram_map = array();
foreach ($repositories as $repository) {
foreach ($repository->getAllMonograms() as $monogram) {
$monogram_map[$monogram] = $repository;
}
}
foreach ($this->monogramIdentifiers as $monogram) {
if (isset($monogram_map[$monogram])) {
$this->identifierMap[$monogram] = $monogram_map[$monogram];
}
}
}
if ($this->slugIdentifiers) {
$slug_map = array();
foreach ($repositories as $repository) {
$slug = $repository->getRepositorySlug();
if ($slug === null) {
continue;
}
$normal = phutil_utf8_strtolower($slug);
$slug_map[$normal] = $repository;
}
foreach ($this->slugIdentifiers as $slug) {
$normal = phutil_utf8_strtolower($slug);
if (isset($slug_map[$normal])) {
$this->identifierMap[$slug] = $slug_map[$normal];
}
}
}
return $repositories;
}
protected function didFilterPage(array $repositories) {
if ($this->needProjectPHIDs) {
$type_project = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($repositories, 'getPHID'))
->withEdgeTypes(array($type_project));
$edge_query->execute();
foreach ($repositories as $repository) {
$project_phids = $edge_query->getDestinationPHIDs(
array(
$repository->getPHID(),
));
$repository->attachProjectPHIDs($project_phids);
}
}
$viewer = $this->getViewer();
if ($this->needURIs) {
$uris = id(new PhabricatorRepositoryURIQuery())
->setViewer($viewer)
->withRepositories($repositories)
->execute();
$uri_groups = mgroup($uris, 'getRepositoryPHID');
foreach ($repositories as $repository) {
$repository_uris = idx($uri_groups, $repository->getPHID(), array());
$repository->attachURIs($repository_uris);
}
}
if ($this->needProfileImage) {
$default = null;
$file_phids = mpull($repositories, 'getProfileImagePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($repositories as $repository) {
$file = idx($files, $repository->getProfileImagePHID());
if (!$file) {
if (!$default) {
$default = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'repo/code.png');
}
$file = $default;
}
$repository->attachProfileImageFile($file);
}
}
return $repositories;
}
protected function getPrimaryTableAlias() {
return 'r';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'committed' => array(
'table' => 's',
'column' => 'epoch',
'type' => 'int',
'null' => 'tail',
),
'callsign' => array(
'table' => 'r',
'column' => 'callsign',
'type' => 'string',
'unique' => true,
'reverse' => true,
'null' => 'tail',
),
'name' => array(
'table' => 'r',
'column' => 'name',
'type' => 'string',
'reverse' => true,
),
'size' => array(
'table' => 's',
'column' => 'size',
'type' => 'int',
'null' => 'tail',
),
);
}
protected function newPagingMapFromCursorObject(
PhabricatorQueryCursor $cursor,
array $keys) {
$repository = $cursor->getObject();
$map = array(
'id' => (int)$repository->getID(),
'callsign' => $repository->getCallsign(),
'name' => $repository->getName(),
);
if (isset($keys['committed'])) {
$map['committed'] = $cursor->getRawRowProperty('epoch');
}
if (isset($keys['size'])) {
$map['size'] = $cursor->getRawRowProperty('size');
}
return $map;
}
protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) {
$parts = parent::buildSelectClauseParts($conn);
if ($this->shouldJoinSummaryTable()) {
$parts[] = qsprintf($conn, 's.*');
}
return $parts;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->shouldJoinSummaryTable()) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T s ON r.id = s.repositoryID',
PhabricatorRepository::TABLE_SUMMARY);
}
if ($this->shouldJoinURITable()) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %R uri ON r.phid = uri.repositoryPHID',
new PhabricatorRepositoryURIIndex());
}
return $joins;
}
protected function shouldGroupQueryResultRows() {
if ($this->shouldJoinURITable()) {
return true;
}
return parent::shouldGroupQueryResultRows();
}
private function shouldJoinURITable() {
return ($this->uris !== null);
}
private function shouldJoinSummaryTable() {
if ($this->needCommitCounts) {
return true;
}
if ($this->needMostRecentCommits) {
return true;
}
$vector = $this->getOrderVector();
if ($vector->containsKey('committed')) {
return true;
}
if ($vector->containsKey('size')) {
return true;
}
return false;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'r.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'r.phid IN (%Ls)',
$this->phids);
}
if ($this->callsigns !== null) {
$where[] = qsprintf(
$conn,
'r.callsign IN (%Ls)',
$this->callsigns);
}
if ($this->numericIdentifiers ||
$this->callsignIdentifiers ||
$this->phidIdentifiers ||
$this->monogramIdentifiers ||
$this->slugIdentifiers) {
$identifier_clause = array();
if ($this->numericIdentifiers) {
$identifier_clause[] = qsprintf(
$conn,
'r.id IN (%Ld)',
$this->numericIdentifiers);
}
if ($this->callsignIdentifiers) {
$identifier_clause[] = qsprintf(
$conn,
'r.callsign IN (%Ls)',
$this->callsignIdentifiers);
}
if ($this->phidIdentifiers) {
$identifier_clause[] = qsprintf(
$conn,
'r.phid IN (%Ls)',
$this->phidIdentifiers);
}
if ($this->monogramIdentifiers) {
$monogram_callsigns = array();
$monogram_ids = array();
foreach ($this->monogramIdentifiers as $identifier) {
if ($identifier[0] == 'r') {
$monogram_callsigns[] = substr($identifier, 1);
} else {
$monogram_ids[] = substr($identifier, 1);
}
}
if ($monogram_ids) {
$identifier_clause[] = qsprintf(
$conn,
'r.id IN (%Ld)',
$monogram_ids);
}
if ($monogram_callsigns) {
$identifier_clause[] = qsprintf(
$conn,
'r.callsign IN (%Ls)',
$monogram_callsigns);
}
}
if ($this->slugIdentifiers) {
$identifier_clause[] = qsprintf(
$conn,
'r.repositorySlug IN (%Ls)',
$this->slugIdentifiers);
}
$where[] = qsprintf($conn, '%LO', $identifier_clause);
}
if ($this->types) {
$where[] = qsprintf(
$conn,
'r.versionControlSystem IN (%Ls)',
$this->types);
}
if ($this->uuids) {
$where[] = qsprintf(
$conn,
'r.uuid IN (%Ls)',
$this->uuids);
}
if ($this->slugs !== null) {
$where[] = qsprintf(
$conn,
'r.repositorySlug IN (%Ls)',
$this->slugs);
}
if ($this->uris !== null) {
$try_uris = $this->getNormalizedURIs();
$try_uris = array_fuse($try_uris);
$where[] = qsprintf(
$conn,
'uri.repositoryURI IN (%Ls)',
$try_uris);
}
if ($this->almanacServicePHIDs !== null) {
$where[] = qsprintf(
$conn,
'r.almanacServicePHID IN (%Ls)',
$this->almanacServicePHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
private function getNormalizedURIs() {
$normalized_uris = array();
// Since we don't know which type of repository this URI is in the general
// case, just generate all the normalizations. We could refine this in some
// cases: if the query specifies VCS types, or the URI is a git-style URI
// or an `svn+ssh` URI, we could deduce how to normalize it. However, this
// would be more complicated and it's not clear if it matters in practice.
$domain_map = PhabricatorRepositoryURI::getURINormalizerDomainMap();
$types = ArcanistRepositoryURINormalizer::getAllURITypes();
foreach ($this->uris as $uri) {
foreach ($types as $type) {
$normalized_uri = new ArcanistRepositoryURINormalizer($type, $uri);
$normalized_uri->setDomainMap($domain_map);
$normalized_uris[] = $normalized_uri->getNormalizedURI();
}
}
return array_unique($normalized_uris);
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
index a6177c20b5..41cc4aff7f 100644
--- a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
@@ -1,149 +1,149 @@
<?php
final class PhabricatorRepositoryRefCursorQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $refTypes;
private $refNames;
private $datasourceQuery;
private $needPositions;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withRefTypes(array $types) {
$this->refTypes = $types;
return $this;
}
public function withRefNames(array $names) {
$this->refNames = $names;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function needPositions($need) {
$this->needPositions = $need;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryRefCursor();
}
protected function willFilterPage(array $refs) {
$repository_phids = mpull($refs, 'getRepositoryPHID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($refs as $key => $ref) {
$repository = idx($repositories, $ref->getRepositoryPHID());
if (!$repository) {
$this->didRejectResult($ref);
unset($refs[$key]);
continue;
}
$ref->attachRepository($repository);
}
if (!$refs) {
return $refs;
}
if ($this->needPositions) {
$positions = id(new PhabricatorRepositoryRefPosition())->loadAllWhere(
'cursorID IN (%Ld)',
mpull($refs, 'getID'));
$positions = mgroup($positions, 'getCursorID');
foreach ($refs as $key => $ref) {
$ref_positions = idx($positions, $ref->getID(), array());
$ref->attachPositions($ref_positions);
}
}
return $refs;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->refTypes !== null) {
$where[] = qsprintf(
$conn,
'refType IN (%Ls)',
$this->refTypes);
}
if ($this->refNames !== null) {
$name_hashes = array();
foreach ($this->refNames as $name) {
$name_hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn,
'refNameHash IN (%Ls)',
$name_hashes);
}
if (phutil_nonempty_string($this->datasourceQuery)) {
$where[] = qsprintf(
$conn,
'refNameRaw LIKE %>',
$this->datasourceQuery);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
index 90a10e9872..33ae85481d 100644
--- a/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
+++ b/src/applications/repository/query/PhabricatorRepositorySearchEngine.php
@@ -1,287 +1,287 @@
<?php
final class PhabricatorRepositorySearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Repositories');
}
public function getApplicationClassName() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
public function newQuery() {
return id(new PhabricatorRepositoryQuery())
->needProjectPHIDs(true)
->needCommitCounts(true)
->needMostRecentCommits(true)
->needProfileImage(true);
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchStringListField())
->setLabel(pht('Callsigns'))
->setKey('callsigns'),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Short Names'))
->setKey('shortNames'),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Status'))
->setKey('status')
->setOptions($this->getStatusOptions()),
id(new PhabricatorSearchSelectField())
->setLabel(pht('Hosted'))
->setKey('hosted')
->setOptions($this->getHostedOptions()),
id(new PhabricatorSearchCheckboxesField())
->setLabel(pht('Types'))
->setKey('types')
->setOptions(PhabricatorRepositoryType::getAllRepositoryTypes()),
id(new PhabricatorSearchStringListField())
->setLabel(pht('URIs'))
->setKey('uris')
->setDescription(
pht('Search for repositories by clone/checkout URI.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Services'))
->setKey('almanacServicePHIDs')
->setAliases(
array(
'almanacServicePHID',
'almanacService',
'almanacServices',
)),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['callsigns']) {
$query->withCallsigns($map['callsigns']);
}
if ($map['shortNames']) {
$query->withSlugs($map['shortNames']);
}
if ($map['status']) {
$status = idx($this->getStatusValues(), $map['status']);
if ($status) {
$query->withStatus($status);
}
}
if ($map['hosted']) {
$hosted = idx($this->getHostedValues(), $map['hosted']);
if ($hosted) {
$query->withHosted($hosted);
}
}
if ($map['types']) {
$query->withTypes($map['types']);
}
if ($map['uris']) {
$query->withURIs($map['uris']);
}
if ($map['almanacServicePHIDs']) {
$query->withAlmanacServicePHIDs($map['almanacServicePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/diffusion/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Repositories'),
'all' => pht('All Repositories'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter('status', 'open');
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
'' => pht('Active and Inactive Repositories'),
'open' => pht('Active Repositories'),
'closed' => pht('Inactive Repositories'),
);
}
private function getStatusValues() {
return array(
'' => PhabricatorRepositoryQuery::STATUS_ALL,
'open' => PhabricatorRepositoryQuery::STATUS_OPEN,
'closed' => PhabricatorRepositoryQuery::STATUS_CLOSED,
);
}
private function getHostedOptions() {
return array(
'' => pht('Hosted and Remote Repositories'),
'phabricator' => pht('Hosted Repositories'),
'remote' => pht('Remote Repositories'),
);
}
private function getHostedValues() {
return array(
'' => PhabricatorRepositoryQuery::HOSTED_ALL,
'phabricator' => PhabricatorRepositoryQuery::HOSTED_PHABRICATOR,
'remote' => PhabricatorRepositoryQuery::HOSTED_REMOTE,
);
}
protected function getRequiredHandlePHIDsForResultList(
array $repositories,
PhabricatorSavedQuery $query) {
return array_mergev(mpull($repositories, 'getProjectPHIDs'));
}
protected function renderResultList(
array $repositories,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($repositories, 'PhabricatorRepository');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($repositories as $repository) {
$id = $repository->getID();
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($repository)
->setHeader($repository->getName())
->setObjectName($repository->getMonogram())
->setHref($repository->getURI())
->setImageURI($repository->getProfileImageURI());
$commit = $repository->getMostRecentCommit();
if ($commit) {
$commit_link = phutil_tag(
'a',
array(
'href' => $commit->getURI(),
),
pht(
'%s: %s',
$commit->getLocalName(),
$commit->getSummary()));
$item->setSubhead($commit_link);
$item->setEpoch($commit->getEpoch());
}
$item->addIcon(
'none',
PhabricatorRepositoryType::getNameForRepositoryType(
$repository->getVersionControlSystem()));
$size = $repository->getCommitCount();
if ($size) {
$history_uri = $repository->generateURI(
array(
'action' => 'history',
));
$item->addAttribute(
phutil_tag(
'a',
array(
'href' => $history_uri,
),
pht('%s Commit(s)', new PhutilNumber($size))));
} else {
$item->addAttribute(pht('No Commits'));
}
$project_handles = array_select_keys(
$handles,
$repository->getProjectPHIDs());
if ($project_handles) {
$item->addAttribute(
id(new PHUIHandleTagListView())
->setSlim(true)
->setHandles($project_handles));
}
if (!$repository->isTracked()) {
$item->setDisabled(true);
$item->addIcon('disable-grey', pht('Inactive'));
} else if ($repository->isImporting()) {
$item->addIcon('fa-clock-o indigo', pht('Importing...'));
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No repositories found for this query.'));
return $result;
}
protected function willUseSavedQuery(PhabricatorSavedQuery $saved) {
$project_phids = $saved->getParameter('projectPHIDs', array());
$old = $saved->getParameter('projects', array());
foreach ($old as $phid) {
$project_phids[] = $phid;
}
$any = $saved->getParameter('anyProjectPHIDs', array());
foreach ($any as $project) {
$project_phids[] = 'any('.$project.')';
}
$saved->setParameter('projectPHIDs', $project_phids);
}
protected function getNewUserBody() {
$new_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('New Repository'))
->setHref('/diffusion/edit/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Import, create, or just browse repositories in Diffusion.'))
->addAction($new_button);
return $view;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
index cc568ef8e1..983187ffab 100644
--- a/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
@@ -1,111 +1,111 @@
<?php
final class PhabricatorRepositorySyncEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $epochMin;
private $epochMax;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withEpochBetween($min, $max) {
$this->epochMin = $min;
$this->epochMax = $max;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositorySyncEvent();
}
protected function willFilterPage(array $events) {
$repository_phids = mpull($events, 'getRepositoryPHID');
$repository_phids = array_filter($repository_phids);
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
} else {
$repositories = array();
}
foreach ($events as $key => $event) {
$phid = $event->getRepositoryPHID();
if (empty($repositories[$phid])) {
unset($events[$key]);
$this->didRejectResult($event);
continue;
}
$event->attachRepository($repositories[$phid]);
}
return $events;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'epoch >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'epoch <= %d',
$this->epochMax);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryURIQuery.php b/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
index 5b75e1ef63..566aa0977f 100644
--- a/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryURIQuery.php
@@ -1,97 +1,97 @@
<?php
final class PhabricatorRepositoryURIQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $repositories = array();
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withRepositories(array $repositories) {
$repositories = mpull($repositories, null, 'getPHID');
$this->withRepositoryPHIDs(array_keys($repositories));
$this->repositories = $repositories;
return $this;
}
public function newResultObject() {
return new PhabricatorRepositoryURI();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
return $where;
}
protected function willFilterPage(array $uris) {
$repositories = $this->repositories;
$repository_phids = mpull($uris, 'getRepositoryPHID');
$repository_phids = array_fuse($repository_phids);
$repository_phids = array_diff_key($repository_phids, $repositories);
if ($repository_phids) {
$more_repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories += mpull($more_repositories, null, 'getPHID');
}
foreach ($uris as $key => $uri) {
$repository_phid = $uri->getRepositoryPHID();
$repository = idx($repositories, $repository_phid);
if (!$repository) {
$this->didRejectResult($uri);
unset($uris[$key]);
continue;
}
$uri->attachRepository($repository);
}
return $uris;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDiffusionApplication';
+ return PhabricatorDiffusionApplication::class;
}
}
diff --git a/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php
index b55f43255c..445be7777f 100644
--- a/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php
+++ b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php
@@ -1,195 +1,195 @@
<?php
final class PhabricatorProfileMenuEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'search.profilemenu';
private $menuEngine;
private $profileObject;
private $customPHID;
private $newMenuItemConfiguration;
private $isBuiltin;
public function isEngineConfigurable() {
return false;
}
public function setMenuEngine(PhabricatorProfileMenuEngine $engine) {
$this->menuEngine = $engine;
return $this;
}
public function getMenuEngine() {
return $this->menuEngine;
}
public function setProfileObject($profile_object) {
$this->profileObject = $profile_object;
return $this;
}
public function getProfileObject() {
return $this->profileObject;
}
public function setCustomPHID($custom_phid) {
$this->customPHID = $custom_phid;
return $this;
}
public function getCustomPHID() {
return $this->customPHID;
}
public function setNewMenuItemConfiguration(
PhabricatorProfileMenuItemConfiguration $configuration) {
$this->newMenuItemConfiguration = $configuration;
return $this;
}
public function getNewMenuItemConfiguration() {
return $this->newMenuItemConfiguration;
}
public function setIsBuiltin($is_builtin) {
$this->isBuiltin = $is_builtin;
return $this;
}
public function getIsBuiltin() {
return $this->isBuiltin;
}
public function getEngineName() {
return pht('Profile Menu Items');
}
public function getSummaryHeader() {
return pht('Edit Profile Menu Item Configurations');
}
public function getSummaryText() {
return pht('This engine is used to modify menu items on profiles.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
protected function newEditableObject() {
if (!$this->newMenuItemConfiguration) {
throw new Exception(
pht(
'Profile menu items can not be generated without an '.
'object context.'));
}
return clone $this->newMenuItemConfiguration;
}
protected function newObjectQuery() {
return id(new PhabricatorProfileMenuItemConfigurationQuery());
}
protected function getObjectCreateTitleText($object) {
if ($this->getIsBuiltin()) {
return pht('Edit Builtin Item');
} else {
return pht('Create Menu Item');
}
}
protected function getObjectCreateButtonText($object) {
if ($this->getIsBuiltin()) {
return pht('Save Changes');
} else {
return pht('Create Menu Item');
}
}
protected function getObjectEditTitleText($object) {
$object->willGetMenuItemViewList(array($object));
return pht('Edit Menu Item: %s', $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return pht('Edit Menu Item');
}
protected function getObjectCreateShortText() {
return pht('Edit Menu Item');
}
protected function getObjectName() {
return pht('Menu Item');
}
protected function getObjectCreateCancelURI($object) {
return $this->getMenuEngine()->getConfigureURI();
}
protected function getObjectViewURI($object) {
return $this->getMenuEngine()->getConfigureURI();
}
protected function buildCustomEditFields($object) {
$item = $object->getMenuItem();
$fields = $item->buildEditEngineFields($object);
$type_property =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY;
foreach ($fields as $field) {
$field
->setTransactionType($type_property)
->setMetadataValue('property.key', $field->getKey());
}
return $fields;
}
protected function getValidationExceptionShortMessage(
PhabricatorApplicationTransactionValidationException $ex,
PhabricatorEditField $field) {
// Menu item properties all have the same transaction type, so we need
// to make sure errors about a specific property (like the URI for a
// link) are only applied to the field for that particular property. If
// we don't do this, the red error text like "Required" will display
// next to every field.
$property_type =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY;
$xaction_type = $field->getTransactionType();
if ($xaction_type == $property_type) {
$field_key = $field->getKey();
foreach ($ex->getErrors() as $error) {
if ($error->getType() !== $xaction_type) {
continue;
}
$xaction = $error->getTransaction();
if (!$xaction) {
continue;
}
$xaction_setting = $xaction->getMetadataValue('property.key');
if ($xaction_setting != $field_key) {
continue;
}
$short_message = $error->getShortMessage();
if ($short_message !== null) {
return $short_message;
}
}
return null;
}
return parent::getValidationExceptionShortMessage($ex, $field);
}
}
diff --git a/src/applications/search/editor/PhabricatorProfileMenuEditor.php b/src/applications/search/editor/PhabricatorProfileMenuEditor.php
index 71f8c32e94..d385c8e90e 100644
--- a/src/applications/search/editor/PhabricatorProfileMenuEditor.php
+++ b/src/applications/search/editor/PhabricatorProfileMenuEditor.php
@@ -1,128 +1,128 @@
<?php
final class PhabricatorProfileMenuEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Profile Menu Items');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY;
$types[] =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER;
$types[] =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue('property.key');
return $object->getMenuItemProperty($key, null);
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER:
return $object->getMenuItemOrder();
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY:
return $object->getVisibility();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY:
return $xaction->getNewValue();
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER:
return (int)$xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
$key = $xaction->getMetadataValue('property.key');
$value = $xaction->getNewValue();
$object->setMenuItemProperty($key, $value);
return;
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER:
$object->setMenuItemOrder($xaction->getNewValue());
return;
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY:
$object->setVisibility($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER:
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$actor = $this->getActor();
$menu_item = $object->getMenuItem();
$menu_item->setViewer($actor);
switch ($type) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
$key_map = array();
foreach ($xactions as $xaction) {
$xaction_key = $xaction->getMetadataValue('property.key');
$old = $this->getCustomTransactionOldValue($object, $xaction);
$new = $xaction->getNewValue();
$key_map[$xaction_key][] = array(
'xaction' => $xaction,
'old' => $old,
'new' => $new,
);
}
foreach ($object->validateTransactions($key_map) as $error) {
$errors[] = $error;
}
break;
}
return $errors;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php
index 0fbdcaca48..53f248114e 100644
--- a/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php
+++ b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorProfileMenuItemPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'PANL';
public function getTypeName() {
return pht('Profile Menu Item');
}
public function newObject() {
return new PhabricatorProfileMenuItemConfiguration();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
return id(new PhabricatorProfileMenuItemConfigurationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$config = $objects[$phid];
$handle->setName(pht('Profile Menu Item'));
}
}
}
diff --git a/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php b/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
index 862f694fc8..82778fa1e2 100644
--- a/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
+++ b/src/applications/search/query/PhabricatorNamedQueryConfigQuery.php
@@ -1,60 +1,60 @@
<?php
final class PhabricatorNamedQueryConfigQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $engineClassNames;
private $scopePHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withScopePHIDs(array $scope_phids) {
$this->scopePHIDs = $scope_phids;
return $this;
}
public function withEngineClassNames(array $engine_class_names) {
$this->engineClassNames = $engine_class_names;
return $this;
}
public function newResultObject() {
return new PhabricatorNamedQueryConfig();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->engineClassNames !== null) {
$where[] = qsprintf(
$conn,
'engineClassName IN (%Ls)',
$this->engineClassNames);
}
if ($this->scopePHIDs !== null) {
$where[] = qsprintf(
$conn,
'scopePHID IN (%Ls)',
$this->scopePHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
}
diff --git a/src/applications/search/query/PhabricatorNamedQueryQuery.php b/src/applications/search/query/PhabricatorNamedQueryQuery.php
index 0ed92646e6..3d57005745 100644
--- a/src/applications/search/query/PhabricatorNamedQueryQuery.php
+++ b/src/applications/search/query/PhabricatorNamedQueryQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorNamedQueryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $engineClassNames;
private $userPHIDs;
private $queryKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withEngineClassNames(array $engine_class_names) {
$this->engineClassNames = $engine_class_names;
return $this;
}
public function withQueryKeys(array $query_keys) {
$this->queryKeys = $query_keys;
return $this;
}
public function newResultObject() {
return new PhabricatorNamedQuery();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->engineClassNames !== null) {
$where[] = qsprintf(
$conn,
'engineClassName IN (%Ls)',
$this->engineClassNames);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->queryKeys !== null) {
$where[] = qsprintf(
$conn,
'queryKey IN (%Ls)',
$this->queryKeys);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
}
diff --git a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
index 9f26a81424..0d26dace7a 100644
--- a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
+++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
@@ -1,159 +1,159 @@
<?php
final class PhabricatorProfileMenuItemConfigurationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $profilePHIDs;
private $customPHIDs;
private $includeGlobal;
private $affectedObjectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProfilePHIDs(array $phids) {
$this->profilePHIDs = $phids;
return $this;
}
public function withCustomPHIDs(array $phids, $include_global = false) {
$this->customPHIDs = $phids;
$this->includeGlobal = $include_global;
return $this;
}
public function withAffectedObjectPHIDs(array $phids) {
$this->affectedObjectPHIDs = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorProfileMenuItemConfiguration();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'config.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'config.phid IN (%Ls)',
$this->phids);
}
if ($this->profilePHIDs !== null) {
$where[] = qsprintf(
$conn,
'config.profilePHID IN (%Ls)',
$this->profilePHIDs);
}
if ($this->customPHIDs !== null) {
if ($this->customPHIDs && $this->includeGlobal) {
$where[] = qsprintf(
$conn,
'config.customPHID IN (%Ls) OR config.customPHID IS NULL',
$this->customPHIDs);
} else if ($this->customPHIDs) {
$where[] = qsprintf(
$conn,
'config.customPHID IN (%Ls)',
$this->customPHIDs);
} else {
$where[] = qsprintf(
$conn,
'config.customPHID IS NULL');
}
}
if ($this->affectedObjectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'affected.dst IN (%Ls)',
$this->affectedObjectPHIDs);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->affectedObjectPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T affected ON affected.src = config.phid
AND affected.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProfileMenuItemAffectsObjectEdgeType::EDGECONST);
}
return $joins;
}
protected function willFilterPage(array $page) {
$items = PhabricatorProfileMenuItem::getAllMenuItems();
foreach ($page as $key => $item) {
$item_type = idx($items, $item->getMenuItemKey());
if (!$item_type) {
$this->didRejectResult($item);
unset($page[$key]);
continue;
}
$item_type = clone $item_type;
$item_type->setViewer($this->getViewer());
$item->attachMenuItem($item_type);
}
if (!$page) {
return array();
}
$profile_phids = mpull($page, 'getProfilePHID');
$profiles = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($profile_phids)
->execute();
$profiles = mpull($profiles, null, 'getPHID');
foreach ($page as $key => $item) {
$profile = idx($profiles, $item->getProfilePHID());
if (!$profile) {
$this->didRejectResult($item);
unset($page[$key]);
continue;
}
$item->attachProfileObject($profile);
}
return $page;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
protected function getPrimaryTableAlias() {
return 'config';
}
}
diff --git a/src/applications/search/query/PhabricatorSavedQueryQuery.php b/src/applications/search/query/PhabricatorSavedQueryQuery.php
index 765c751940..d8e939d424 100644
--- a/src/applications/search/query/PhabricatorSavedQueryQuery.php
+++ b/src/applications/search/query/PhabricatorSavedQueryQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorSavedQueryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $engineClassNames;
private $queryKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withEngineClassNames(array $engine_class_names) {
$this->engineClassNames = $engine_class_names;
return $this;
}
public function withQueryKeys(array $query_keys) {
$this->queryKeys = $query_keys;
return $this;
}
protected function loadPage() {
$table = new PhabricatorSavedQuery();
$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->engineClassNames !== null) {
$where[] = qsprintf(
$conn,
'engineClassName IN (%Ls)',
$this->engineClassNames);
}
if ($this->queryKeys !== null) {
$where[] = qsprintf(
$conn,
'queryKey IN (%Ls)',
$this->queryKeys);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($conn, $where);
}
public function getQueryApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
}
diff --git a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
index 3fcf0a8f7a..dca98e8411 100644
--- a/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
+++ b/src/applications/search/query/PhabricatorSearchApplicationSearchEngine.php
@@ -1,313 +1,313 @@
<?php
final class PhabricatorSearchApplicationSearchEngine
extends PhabricatorApplicationSearchEngine {
private $resultSet;
public function getResultTypeDescription() {
return pht('Fulltext Search Results');
}
public function getApplicationClassName() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('query', $request->getStr('query'));
$saved->setParameter(
'statuses',
$this->readListFromRequest($request, 'statuses'));
$saved->setParameter(
'types',
$this->readListFromRequest($request, 'types'));
$saved->setParameter(
'authorPHIDs',
$this->readUsersFromRequest($request, 'authorPHIDs'));
$saved->setParameter(
'ownerPHIDs',
$this->readUsersFromRequest($request, 'ownerPHIDs'));
$saved->setParameter(
'subscriberPHIDs',
$this->readSubscribersFromRequest($request, 'subscriberPHIDs'));
$saved->setParameter(
'projectPHIDs',
$this->readPHIDsFromRequest($request, 'projectPHIDs'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = new PhabricatorSearchDocumentQuery();
// Convert the saved query into a resolved form (without typeahead
// functions) which the fulltext search engines can execute.
$config = clone $saved;
$viewer = $this->requireViewer();
$datasource = id(new PhabricatorPeopleOwnerDatasource())
->setViewer($viewer);
$owner_phids = $this->readOwnerPHIDs($config);
$owner_phids = $datasource->evaluateTokens($owner_phids);
foreach ($owner_phids as $key => $phid) {
if ($phid == PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN) {
$config->setParameter('withUnowned', true);
unset($owner_phids[$key]);
}
if ($phid == PhabricatorPeopleAnyOwnerDatasource::FUNCTION_TOKEN) {
$config->setParameter('withAnyOwner', true);
unset($owner_phids[$key]);
}
}
$config->setParameter('ownerPHIDs', $owner_phids);
$datasource = id(new PhabricatorPeopleUserFunctionDatasource())
->setViewer($viewer);
$author_phids = $config->getParameter('authorPHIDs', array());
$author_phids = $datasource->evaluateTokens($author_phids);
$config->setParameter('authorPHIDs', $author_phids);
$datasource = id(new PhabricatorMetaMTAMailableFunctionDatasource())
->setViewer($viewer);
$subscriber_phids = $config->getParameter('subscriberPHIDs', array());
$subscriber_phids = $datasource->evaluateTokens($subscriber_phids);
$config->setParameter('subscriberPHIDs', $subscriber_phids);
$query->withSavedQuery($config);
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$options = array();
$author_value = null;
$owner_value = null;
$subscribers_value = null;
$project_value = null;
$author_phids = $saved->getParameter('authorPHIDs', array());
$owner_phids = $this->readOwnerPHIDs($saved);
$subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
$project_phids = $saved->getParameter('projectPHIDs', array());
$status_values = $saved->getParameter('statuses', array());
$status_values = array_fuse($status_values);
$statuses = array(
PhabricatorSearchRelationship::RELATIONSHIP_OPEN => pht('Open'),
PhabricatorSearchRelationship::RELATIONSHIP_CLOSED => pht('Closed'),
);
$status_control = id(new AphrontFormCheckboxControl())
->setLabel(pht('Document Status'));
foreach ($statuses as $status => $name) {
$status_control->addCheckbox(
'statuses[]',
$status,
$name,
isset($status_values[$status]));
}
$type_values = $saved->getParameter('types', array());
$type_values = array_fuse($type_values);
$types_control = id(new AphrontFormTokenizerControl())
->setLabel(pht('Document Types'))
->setName('types')
->setDatasource(new PhabricatorSearchDocumentTypeDatasource())
->setValue($type_values);
$form
->appendChild(
phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => 'jump',
'value' => 'no',
)))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Query'))
->setName('query')
->setValue($saved->getParameter('query')))
->appendChild($status_control)
->appendControl($types_control)
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('authorPHIDs')
->setLabel(pht('Authors'))
->setDatasource(new PhabricatorPeopleUserFunctionDatasource())
->setValue($author_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('ownerPHIDs')
->setLabel(pht('Owners'))
->setDatasource(new PhabricatorPeopleOwnerDatasource())
->setValue($owner_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('subscriberPHIDs')
->setLabel(pht('Subscribers'))
->setDatasource(new PhabricatorMetaMTAMailableFunctionDatasource())
->setValue($subscriber_phids))
->appendControl(
id(new AphrontFormTokenizerControl())
->setName('projectPHIDs')
->setLabel(pht('Tags'))
->setDatasource(new PhabricatorProjectDatasource())
->setValue($project_phids));
}
protected function getURI($path) {
return '/search/'.$path;
}
protected function getBuiltinQueryNames() {
return array(
'all' => pht('All Documents'),
'open' => pht('Open Documents'),
'open-tasks' => pht('Open Tasks'),
);
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'open':
return $query->setParameter('statuses', array('open'));
case 'open-tasks':
return $query
->setParameter('statuses', array('open'))
->setParameter('types', array(ManiphestTaskPHIDType::TYPECONST));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
public static function getIndexableDocumentTypes(
PhabricatorUser $viewer = null) {
// TODO: This is inelegant and not very efficient, but gets us reasonable
// results. It would be nice to do this more elegantly.
$objects = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorFulltextInterface')
->execute();
$type_map = array();
foreach ($objects as $object) {
$phid_type = phid_get_type($object->generatePHID());
$type_map[$phid_type] = $object;
}
if ($viewer) {
$types = PhabricatorPHIDType::getAllInstalledTypes($viewer);
} else {
$types = PhabricatorPHIDType::getAllTypes();
}
$results = array();
foreach ($types as $type) {
$typeconst = $type->getTypeConstant();
$object = idx($type_map, $typeconst);
if ($object) {
$results[$typeconst] = $type->getTypeName();
}
}
asort($results);
return $results;
}
public function shouldUseOffsetPaging() {
return true;
}
protected function renderResultList(
array $results,
PhabricatorSavedQuery $query,
array $handles) {
$result_set = $this->resultSet;
$fulltext_tokens = $result_set->getFulltextTokens();
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setNoDataString(pht('No results found.'));
if ($results) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(mpull($results, 'getPHID'))
->execute();
foreach ($results as $phid => $handle) {
$view = id(new PhabricatorSearchResultView())
->setHandle($handle)
->setTokens($fulltext_tokens)
->setObject(idx($objects, $phid))
->render();
$list->addItem($view);
}
}
$fulltext_view = null;
if ($fulltext_tokens) {
require_celerity_resource('phabricator-search-results-css');
$fulltext_view = array();
foreach ($fulltext_tokens as $token) {
$fulltext_view[] = $token->newTag();
}
$fulltext_view = phutil_tag(
'div',
array(
'class' => 'phui-fulltext-tokens',
),
array(
pht('Searched For:'),
' ',
$fulltext_view,
));
}
$result = new PhabricatorApplicationSearchResultView();
$result->setContent($fulltext_view);
$result->setObjectList($list);
return $result;
}
private function readOwnerPHIDs(PhabricatorSavedQuery $saved) {
$owner_phids = $saved->getParameter('ownerPHIDs', array());
// This was an old checkbox from before typeahead functions.
if ($saved->getParameter('withUnowned')) {
$owner_phids[] = PhabricatorPeopleNoOwnerDatasource::FUNCTION_TOKEN;
}
return $owner_phids;
}
protected function didExecuteQuery(PhabricatorPolicyAwareQuery $query) {
$this->resultSet = $query->getFulltextResultSet();
}
}
diff --git a/src/applications/search/query/PhabricatorSearchDocumentQuery.php b/src/applications/search/query/PhabricatorSearchDocumentQuery.php
index 4aed4722bd..7282b33efb 100644
--- a/src/applications/search/query/PhabricatorSearchDocumentQuery.php
+++ b/src/applications/search/query/PhabricatorSearchDocumentQuery.php
@@ -1,111 +1,111 @@
<?php
final class PhabricatorSearchDocumentQuery
extends PhabricatorPolicyAwareQuery {
private $savedQuery;
private $objectCapabilities;
private $unfilteredOffset;
private $fulltextResultSet;
public function withSavedQuery(PhabricatorSavedQuery $query) {
$this->savedQuery = $query;
return $this;
}
public function requireObjectCapabilities(array $capabilities) {
$this->objectCapabilities = $capabilities;
return $this;
}
protected function getRequiredObjectCapabilities() {
if ($this->objectCapabilities) {
return $this->objectCapabilities;
}
return $this->getRequiredCapabilities();
}
public function getFulltextResultSet() {
if (!$this->fulltextResultSet) {
throw new PhutilInvalidStateException('execute');
}
return $this->fulltextResultSet;
}
protected function willExecute() {
$this->unfilteredOffset = 0;
$this->fulltextResultSet = null;
}
protected function loadPage() {
// NOTE: The offset and limit information in the inherited properties of
// this object represent a policy-filtered offset and limit, but the
// underlying query engine needs an unfiltered offset and limit. We keep
// track of an unfiltered result offset internally.
$query = id(clone($this->savedQuery))
->setParameter('offset', $this->unfilteredOffset)
->setParameter('limit', $this->getRawResultLimit());
$result_set = PhabricatorSearchService::newResultSet($query, $this);
$phids = $result_set->getPHIDs();
$this->fulltextResultSet = $result_set;
$this->unfilteredOffset += count($phids);
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->requireObjectCapabilities($this->getRequiredObjectCapabilities())
->withPHIDs($phids)
->execute();
// Retain engine order.
$handles = array_select_keys($handles, $phids);
return $handles;
}
protected function willFilterPage(array $handles) {
// NOTE: This is used by the object selector dialog to exclude the object
// you're looking at, so that, e.g., a task can't be set as a dependency
// of itself in the UI.
// TODO: Remove this after object selection moves to ApplicationSearch.
$exclude = array();
if ($this->savedQuery) {
$exclude_phids = $this->savedQuery->getParameter('excludePHIDs', array());
$exclude = array_fuse($exclude_phids);
}
foreach ($handles as $key => $handle) {
if (!$handle->isComplete()) {
unset($handles[$key]);
continue;
}
if ($handle->getPolicyFiltered()) {
unset($handles[$key]);
continue;
}
if (isset($exclude[$handle->getPHID()])) {
unset($handles[$key]);
continue;
}
}
return $handles;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
protected function nextPage(array $page) {
// We already updated the internal offset in `loadPage()` after loading
// results, so we do not need to make any additional state updates here.
return $this;
}
}
diff --git a/src/applications/search/typeahead/PhabricatorSearchDatasource.php b/src/applications/search/typeahead/PhabricatorSearchDatasource.php
index 2d8182a2a2..c609d022bb 100644
--- a/src/applications/search/typeahead/PhabricatorSearchDatasource.php
+++ b/src/applications/search/typeahead/PhabricatorSearchDatasource.php
@@ -1,31 +1,31 @@
<?php
final class PhabricatorSearchDatasource
extends PhabricatorTypeaheadCompositeDatasource {
public function getBrowseTitle() {
return pht('Browse Results');
}
public function getPlaceholderText() {
return pht('Type an object name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
public function getComponentDatasources() {
$sources = id(new PhabricatorDatasourceEngine())
->getAllQuickSearchDatasources();
// These results are always rendered in the full browse display mode, so
// set the browse flag on all component sources.
foreach ($sources as $source) {
$source->setIsBrowse(true);
}
return $sources;
}
}
diff --git a/src/applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php b/src/applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php
index c99cc4ede3..9b94d0b24d 100644
--- a/src/applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php
+++ b/src/applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php
@@ -1,57 +1,57 @@
<?php
final class PhabricatorSearchDocumentTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Document Types');
}
public function getPlaceholderText() {
return pht('Select a document type...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorSearchApplication';
+ return PhabricatorSearchApplication::class;
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
public function renderTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$viewer = $this->getViewer();
$types =
PhabricatorSearchApplicationSearchEngine::getIndexableDocumentTypes(
$viewer);
$phid_types = mpull(PhabricatorPHIDType::getAllTypes(),
null,
'getTypeConstant');
$results = array();
foreach ($types as $type => $name) {
$type_object = idx($phid_types, $type);
if (!$type_object) {
continue;
}
$application_class = $type_object->getPHIDTypeApplicationClass();
$application = PhabricatorApplication::getByClass($application_class);
$application_name = $application->getName();
$results[$type] = id(new PhabricatorTypeaheadResult())
->setPHID($type)
->setName($name)
->addAttribute($application_name)
->setIcon($type_object->getTypeIcon());
}
return $results;
}
}
diff --git a/src/applications/settings/editor/PhabricatorSettingsEditEngine.php b/src/applications/settings/editor/PhabricatorSettingsEditEngine.php
index b45de2dce1..a5ae9b3348 100644
--- a/src/applications/settings/editor/PhabricatorSettingsEditEngine.php
+++ b/src/applications/settings/editor/PhabricatorSettingsEditEngine.php
@@ -1,290 +1,290 @@
<?php
final class PhabricatorSettingsEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'settings.settings';
private $isSelfEdit;
private $profileURI;
private $settingsPanel;
public function setIsSelfEdit($is_self_edit) {
$this->isSelfEdit = $is_self_edit;
return $this;
}
public function getIsSelfEdit() {
return $this->isSelfEdit;
}
public function setProfileURI($profile_uri) {
$this->profileURI = $profile_uri;
return $this;
}
public function getProfileURI() {
return $this->profileURI;
}
public function setSettingsPanel($settings_panel) {
$this->settingsPanel = $settings_panel;
return $this;
}
public function getSettingsPanel() {
return $this->settingsPanel;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Settings');
}
public function getSummaryHeader() {
return pht('Edit Settings Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit settings.');
}
public function getEngineApplicationClass() {
- return 'PhabricatorSettingsApplication';
+ return PhabricatorSettingsApplication::class;
}
protected function newEditableObject() {
return new PhabricatorUserPreferences();
}
protected function newObjectQuery() {
return new PhabricatorUserPreferencesQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Settings');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Settings');
}
protected function getObjectEditTitleText($object) {
$page = $this->getSelectedPage();
if ($page) {
return $page->getLabel();
}
return pht('Settings');
}
protected function getObjectEditShortText($object) {
if (!$object->getUser()) {
return pht('Global Defaults');
} else {
if ($this->getIsSelfEdit()) {
return pht('Personal Settings');
} else {
return pht('Account Settings');
}
}
}
protected function getObjectCreateShortText() {
return pht('Create Settings');
}
protected function getObjectName() {
$page = $this->getSelectedPage();
if ($page) {
return $page->getLabel();
}
return pht('Settings');
}
protected function getPageHeader($object) {
$user = $object->getUser();
if ($user) {
$text = pht('Edit Settings: %s', $user->getUserName());
} else {
$text = pht('Edit Global Settings');
}
$header = id(new PHUIHeaderView())
->setHeader($text);
return $header;
}
protected function getEditorURI() {
throw new PhutilMethodNotImplementedException();
}
protected function getObjectCreateCancelURI($object) {
return '/settings/';
}
protected function getObjectViewURI($object) {
return $object->getEditURI();
}
protected function getCreateNewObjectPolicy() {
return PhabricatorPolicies::POLICY_ADMIN;
}
public function getEffectiveObjectEditCancelURI($object) {
if (!$object->getUser()) {
return '/settings/';
}
if ($this->getIsSelfEdit()) {
return null;
}
if ($this->getProfileURI()) {
return $this->getProfileURI();
}
return parent::getEffectiveObjectEditCancelURI($object);
}
protected function newPages($object) {
$viewer = $this->getViewer();
$user = $object->getUser();
$panels = PhabricatorSettingsPanel::getAllDisplayPanels();
foreach ($panels as $key => $panel) {
if (!($panel instanceof PhabricatorEditEngineSettingsPanel)) {
unset($panels[$key]);
continue;
}
$panel->setViewer($viewer);
if ($user) {
$panel->setUser($user);
}
}
$pages = array();
$uris = array();
foreach ($panels as $key => $panel) {
$uris[$key] = $panel->getPanelURI();
$page = $panel->newEditEnginePage();
if (!$page) {
continue;
}
$pages[] = $page;
}
$more_pages = array(
id(new PhabricatorEditPage())
->setKey('extra')
->setLabel(pht('Extra Settings'))
->setIsDefault(true),
);
foreach ($more_pages as $page) {
$pages[] = $page;
}
return $pages;
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
$settings = PhabricatorSetting::getAllEnabledSettings($viewer);
foreach ($settings as $key => $setting) {
$setting = clone $setting;
$setting->setViewer($viewer);
$settings[$key] = $setting;
}
$settings = msortv($settings, 'getSettingOrderVector');
$fields = array();
foreach ($settings as $setting) {
foreach ($setting->newCustomEditFields($object) as $field) {
$fields[] = $field;
}
}
return $fields;
}
protected function getValidationExceptionShortMessage(
PhabricatorApplicationTransactionValidationException $ex,
PhabricatorEditField $field) {
// Settings fields all have the same transaction type so we need to make
// sure the transaction is changing the same setting before matching an
// error to a given field.
$xaction_type = $field->getTransactionType();
if ($xaction_type == PhabricatorUserPreferencesTransaction::TYPE_SETTING) {
$property = PhabricatorUserPreferencesTransaction::PROPERTY_SETTING;
$field_setting = idx($field->getMetadata(), $property);
foreach ($ex->getErrors() as $error) {
if ($error->getType() !== $xaction_type) {
continue;
}
$xaction = $error->getTransaction();
if (!$xaction) {
continue;
}
$xaction_setting = $xaction->getMetadataValue($property);
if ($xaction_setting != $field_setting) {
continue;
}
$short_message = $error->getShortMessage();
if ($short_message !== null) {
return $short_message;
}
}
return null;
}
return parent::getValidationExceptionShortMessage($ex, $field);
}
protected function newEditFormHeadContent(
PhabricatorEditEnginePageState $state) {
$content = array();
if ($state->getIsSave()) {
$content[] = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('Changes saved.'));
}
$panel = $this->getSettingsPanel();
$content[] = $panel->newSettingsPanelEditFormHeadContent($state);
return $content;
}
protected function newEditFormTailContent(
PhabricatorEditEnginePageState $state) {
$content = array();
$panel = $this->getSettingsPanel();
$content[] = $panel->newSettingsPanelEditFormTailContent($state);
return $content;
}
}
diff --git a/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
index a927cc7475..d44766f136 100644
--- a/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
+++ b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
@@ -1,184 +1,184 @@
<?php
final class PhabricatorUserPreferencesEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorSettingsApplication';
+ return PhabricatorSettingsApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Settings');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorUserPreferencesTransaction::TYPE_SETTING;
return $types;
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$settings = $this->getSettings();
$setting = idx($settings, $setting_key);
if ($setting) {
return $setting->expandSettingTransaction($object, $xaction);
}
return parent::expandTransaction($object, $xaction);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
return $object->getPreference($setting_key);
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$actor = $this->getActor();
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$settings = PhabricatorSetting::getAllEnabledSettings($actor);
$setting = $settings[$setting_key];
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
$value = $xaction->getNewValue();
$value = $setting->getTransactionNewValue($value);
return $value;
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
$new_value = $xaction->getNewValue();
if ($new_value === null) {
$object->unsetPreference($setting_key);
} else {
$object->setPreference($setting_key, $new_value);
}
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$settings = $this->getSettings();
switch ($type) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
foreach ($xactions as $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$setting = idx($settings, $setting_key);
if (!$setting) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'There is no known application setting with key "%s".',
$setting_key),
$xaction);
continue;
}
try {
$setting->validateTransactionValue($xaction->getNewValue());
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
}
}
break;
}
return $errors;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$user_phid = $object->getUserPHID();
if ($user_phid) {
PhabricatorUserCache::clearCache(
PhabricatorUserPreferencesCacheType::KEY_PREFERENCES,
$user_phid);
} else {
$cache = PhabricatorCaches::getMutableStructureCache();
$cache->deleteKey(PhabricatorUser::getGlobalSettingsCacheKey());
PhabricatorUserCache::clearCacheForAllUsers(
PhabricatorUserPreferencesCacheType::KEY_PREFERENCES);
}
return $xactions;
}
private function getSettings() {
$actor = $this->getActor();
$settings = PhabricatorSetting::getAllEnabledSettings($actor);
foreach ($settings as $key => $setting) {
$setting = clone $setting;
$setting->setViewer($actor);
$settings[$key] = $setting;
}
return $settings;
}
}
diff --git a/src/applications/settings/phid/PhabricatorUserPreferencesPHIDType.php b/src/applications/settings/phid/PhabricatorUserPreferencesPHIDType.php
index 7022c56c33..ad24ae5af6 100644
--- a/src/applications/settings/phid/PhabricatorUserPreferencesPHIDType.php
+++ b/src/applications/settings/phid/PhabricatorUserPreferencesPHIDType.php
@@ -1,39 +1,39 @@
<?php
final class PhabricatorUserPreferencesPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'PSET';
public function getTypeName() {
return pht('Settings');
}
public function newObject() {
return new PhabricatorUserPreferences();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorSettingsApplication';
+ return PhabricatorSettingsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorUserPreferencesQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
$viewer = $query->getViewer();
foreach ($handles as $phid => $handle) {
$preferences = $objects[$phid];
$handle->setName(pht('Settings %d', $preferences->getID()));
}
}
}
diff --git a/src/applications/settings/query/PhabricatorUserPreferencesQuery.php b/src/applications/settings/query/PhabricatorUserPreferencesQuery.php
index 1a6133724d..5fa9b89bdd 100644
--- a/src/applications/settings/query/PhabricatorUserPreferencesQuery.php
+++ b/src/applications/settings/query/PhabricatorUserPreferencesQuery.php
@@ -1,196 +1,196 @@
<?php
final class PhabricatorUserPreferencesQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $userPHIDs;
private $builtinKeys;
private $hasUserPHID;
private $users = array();
private $synthetic;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withHasUserPHID($is_user) {
$this->hasUserPHID = $is_user;
return $this;
}
public function withUserPHIDs(array $phids) {
$this->userPHIDs = $phids;
return $this;
}
public function withUsers(array $users) {
assert_instances_of($users, 'PhabricatorUser');
$this->users = mpull($users, null, 'getPHID');
$this->withUserPHIDs(array_keys($this->users));
return $this;
}
public function withBuiltinKeys(array $keys) {
$this->builtinKeys = $keys;
return $this;
}
/**
* Always return preferences for every queried user.
*
* If no settings exist for a user, a new empty settings object with
* appropriate defaults is returned.
*
* @param bool True to generate synthetic preferences for missing users.
*/
public function needSyntheticPreferences($synthetic) {
$this->synthetic = $synthetic;
return $this;
}
public function newResultObject() {
return new PhabricatorUserPreferences();
}
protected function loadPage() {
$preferences = $this->loadStandardPage($this->newResultObject());
if ($this->synthetic) {
$user_map = mpull($preferences, null, 'getUserPHID');
foreach ($this->userPHIDs as $user_phid) {
if (isset($user_map[$user_phid])) {
continue;
}
$preferences[] = $this->newResultObject()
->setUserPHID($user_phid);
}
}
return $preferences;
}
protected function willFilterPage(array $prefs) {
$user_phids = mpull($prefs, 'getUserPHID');
$user_phids = array_filter($user_phids);
// If some of the preferences are attached to users, try to use any objects
// we were handed first. If we're missing some, load them.
if ($user_phids) {
$users = $this->users;
$user_phids = array_fuse($user_phids);
$load_phids = array_diff_key($user_phids, $users);
$load_phids = array_keys($load_phids);
if ($load_phids) {
$load_users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withPHIDs($load_phids)
->execute();
$load_users = mpull($load_users, null, 'getPHID');
$users += $load_users;
}
} else {
$users = array();
}
$need_global = array();
foreach ($prefs as $key => $pref) {
$user_phid = $pref->getUserPHID();
if (!$user_phid) {
$pref->attachUser(null);
continue;
}
$need_global[] = $pref;
$user = idx($users, $user_phid);
if (!$user) {
$this->didRejectResult($pref);
unset($prefs[$key]);
continue;
}
$pref->attachUser($user);
}
// If we loaded any user preferences, load the global defaults and attach
// them if they exist.
if ($need_global) {
$global = id(new self())
->setViewer($this->getViewer())
->withBuiltinKeys(
array(
PhabricatorUserPreferences::BUILTIN_GLOBAL_DEFAULT,
))
->executeOne();
if ($global) {
foreach ($need_global as $pref) {
$pref->attachDefaultSettings($global);
}
}
}
return $prefs;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->builtinKeys !== null) {
$where[] = qsprintf(
$conn,
'builtinKey IN (%Ls)',
$this->builtinKeys);
}
if ($this->hasUserPHID !== null) {
if ($this->hasUserPHID) {
$where[] = qsprintf(
$conn,
'userPHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn,
'userPHID IS NULL');
}
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSettingsApplication';
+ return PhabricatorSettingsApplication::class;
}
}
diff --git a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php
index cf088f37d4..14135bf88d 100644
--- a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php
+++ b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php
@@ -1,95 +1,95 @@
<?php
final class PhabricatorSlowvoteEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorSlowvoteApplication';
+ return PhabricatorSlowvoteApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Slowvote');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this poll.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
return $types;
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
public function getMailTagsMap() {
return array(
PhabricatorSlowvoteTransaction::MAILTAG_DETAILS =>
pht('Someone changes the poll details.'),
PhabricatorSlowvoteTransaction::MAILTAG_RESPONSES =>
pht('Someone votes on a poll.'),
PhabricatorSlowvoteTransaction::MAILTAG_OTHER =>
pht('Other poll activity not listed above occurs.'),
);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getQuestion();
return id(new PhabricatorMetaMTAMail())
->setSubject("{$monogram}: {$name}");
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$description = $object->getDescription();
if (strlen($description)) {
$body->addRemarkupSection(
pht('SLOWVOTE DESCRIPTION'),
$object->getDescription());
}
$body->addLinkSection(
pht('SLOWVOTE DETAIL'),
PhabricatorEnv::getProductionURI('/'.$object->getMonogram()));
return $body;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function getMailSubjectPrefix() {
return '[Slowvote]';
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PhabricatorSlowvoteReplyHandler())
->setMailReceiver($object);
}
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
}
diff --git a/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php b/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php
index 42ced85b22..f31ae71588 100644
--- a/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php
+++ b/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php
@@ -1,70 +1,70 @@
<?php
final class PhabricatorSlowvotePollPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'POLL';
public function getTypeName() {
return pht('Slowvote Poll');
}
public function newObject() {
return new PhabricatorSlowvotePoll();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorSlowvoteApplication';
+ return PhabricatorSlowvoteApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorSlowvoteQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$poll = $objects[$phid];
$handle->setName('V'.$poll->getID());
$handle->setFullName('V'.$poll->getID().': '.$poll->getQuestion());
$handle->setURI('/V'.$poll->getID());
}
}
public function canLoadNamedObject($name) {
return preg_match('/^V\d*[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorSlowvoteQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
index d2ae9f1a35..bdc736022a 100644
--- a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
+++ b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
@@ -1,171 +1,171 @@
<?php
final class PhabricatorSlowvoteQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $withVotesByViewer;
private $statuses;
private $needOptions;
private $needChoices;
private $needViewerChoices;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs($author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withVotesByViewer($with_vote) {
$this->withVotesByViewer = $with_vote;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needOptions($need_options) {
$this->needOptions = $need_options;
return $this;
}
public function needChoices($need_choices) {
$this->needChoices = $need_choices;
return $this;
}
public function needViewerChoices($need_viewer_choices) {
$this->needViewerChoices = $need_viewer_choices;
return $this;
}
public function newResultObject() {
return new PhabricatorSlowvotePoll();
}
protected function willFilterPage(array $polls) {
assert_instances_of($polls, 'PhabricatorSlowvotePoll');
$ids = mpull($polls, 'getID');
$viewer = $this->getViewer();
if ($this->needOptions) {
$options = id(new PhabricatorSlowvoteOption())->loadAllWhere(
'pollID IN (%Ld)',
$ids);
$options = mgroup($options, 'getPollID');
foreach ($polls as $poll) {
$poll->attachOptions(idx($options, $poll->getID(), array()));
}
}
if ($this->needChoices) {
$choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
'pollID IN (%Ld)',
$ids);
$choices = mgroup($choices, 'getPollID');
foreach ($polls as $poll) {
$poll->attachChoices(idx($choices, $poll->getID(), array()));
}
// If we need the viewer's choices, we can just fill them from the data
// we already loaded.
if ($this->needViewerChoices) {
foreach ($polls as $poll) {
$poll->attachViewerChoices(
$viewer,
idx(
mgroup($poll->getChoices(), 'getAuthorPHID'),
$viewer->getPHID(),
array()));
}
}
} else if ($this->needViewerChoices) {
$choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
'pollID IN (%Ld) AND authorPHID = %s',
$ids,
$viewer->getPHID());
$choices = mgroup($choices, 'getPollID');
foreach ($polls as $poll) {
$poll->attachViewerChoices(
$viewer,
idx($choices, $poll->getID(), array()));
}
}
return $polls;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'p.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'p.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'p.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'p.status IN (%Ls)',
$this->statuses);
}
return $where;
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
$joins = parent::buildJoinClauseParts($conn);
if ($this->withVotesByViewer !== null) {
$joins[] = qsprintf(
$conn,
'JOIN %T vv ON vv.pollID = p.id AND vv.authorPHID = %s',
id(new PhabricatorSlowvoteChoice())->getTableName(),
$this->getViewer()->getPHID());
}
return $joins;
}
protected function getPrimaryTableAlias() {
return 'p';
}
public function getQueryApplicationClass() {
- return 'PhabricatorSlowvoteApplication';
+ return PhabricatorSlowvoteApplication::class;
}
}
diff --git a/src/applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php b/src/applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php
index 8b93f75faf..557f6b815c 100644
--- a/src/applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php
+++ b/src/applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php
@@ -1,185 +1,185 @@
<?php
final class PhabricatorSlowvoteSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Slowvotes');
}
public function getApplicationClassName() {
- return 'PhabricatorSlowvoteApplication';
+ return PhabricatorSlowvoteApplication::class;
}
public function newQuery() {
return new PhabricatorSlowvoteQuery();
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['voted']) {
$query->withVotesByViewer(true);
}
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
if ($map['statuses']) {
$query->withStatuses($map['statuses']);
}
return $query;
}
protected function buildCustomSearchFields() {
$status_options = SlowvotePollStatus::getAll();
$status_options = mpull($status_options, 'getName');
return array(
id(new PhabricatorUsersSearchField())
->setKey('authorPHIDs')
->setAliases(array('authors'))
->setLabel(pht('Authors')),
id(new PhabricatorSearchCheckboxesField())
->setKey('voted')
->setLabel(pht('Voted'))
// TODO: This should probably become a list of "voterPHIDs", so hide
// the field from Conduit to avoid a backward compatibility break when
// this changes.
->setEnableForConduit(false)
->setOptions(array(
'voted' => pht("Show only polls I've voted in."),
)),
id(new PhabricatorSearchCheckboxesField())
->setKey('statuses')
->setLabel(pht('Statuses'))
->setOptions($status_options),
);
}
protected function getURI($path) {
return '/vote/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'open' => pht('Open Polls'),
'all' => pht('All Polls'),
);
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored');
$names['voted'] = pht('Voted In');
}
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'open':
return $query->setParameter('statuses', array('open'));
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
case 'voted':
return $query->setParameter('voted', array('voted'));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $polls,
PhabricatorSavedQuery $query) {
return mpull($polls, 'getAuthorPHID');
}
protected function renderResultList(
array $polls,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($polls, 'PhabricatorSlowvotePoll');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
$phids = mpull($polls, 'getAuthorPHID');
foreach ($polls as $poll) {
$date_created = phabricator_datetime($poll->getDateCreated(), $viewer);
if ($poll->getAuthorPHID()) {
$author = $handles[$poll->getAuthorPHID()]->renderLink();
} else {
$author = null;
}
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setObject($poll)
->setObjectName($poll->getMonogram())
->setHeader($poll->getQuestion())
->setHref($poll->getURI())
->addIcon('none', $date_created);
if ($poll->isClosed()) {
$item->setStatusIcon('fa-ban grey');
$item->setDisabled(true);
} else {
$item->setStatusIcon('fa-bar-chart');
}
$description = $poll->getDescription();
if (strlen($description)) {
$item->addAttribute(id(new PhutilUTF8StringTruncator())
->setMaximumGlyphs(120)
->truncateString($poll->getDescription()));
}
if ($author) {
$item->addByline(pht('Author: %s', $author));
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No polls found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Poll'))
->setHref('/vote/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Poll other users to help facilitate decision making.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php b/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php
index e4dc9c5b69..abfafa491e 100644
--- a/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php
+++ b/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php
@@ -1,31 +1,31 @@
<?php
final class PhabricatorSpacesNamespaceEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return pht('PhabricatorSpacesApplication');
+ return PhabricatorSpacesApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Spaces');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this space.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created space %s.', $author, $object);
}
}
diff --git a/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php b/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php
index 1399e71c8e..a46040f98d 100644
--- a/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php
+++ b/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php
@@ -1,80 +1,80 @@
<?php
final class PhabricatorSpacesNamespacePHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'SPCE';
public function getTypeName() {
return pht('Space');
}
public function newObject() {
return new PhabricatorSpacesNamespace();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorSpacesApplication';
+ return PhabricatorSpacesApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorSpacesNamespaceQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$namespace = $objects[$phid];
$monogram = $namespace->getMonogram();
$name = $namespace->getNamespaceName();
$handle
->setName($name)
->setFullName(pht('%s %s', $monogram, $name))
->setURI('/'.$monogram)
->setMailStampName($monogram);
if ($namespace->getIsArchived()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
}
}
}
public function canLoadNamedObject($name) {
return preg_match('/^S[1-9]\d*$/i', $name);
}
public function loadNamedObjects(
PhabricatorObjectQuery $query,
array $names) {
$id_map = array();
foreach ($names as $name) {
$id = (int)substr($name, 1);
$id_map[$id][] = $name;
}
$objects = id(new PhabricatorSpacesNamespaceQuery())
->setViewer($query->getViewer())
->withIDs(array_keys($id_map))
->execute();
$results = array();
foreach ($objects as $id => $object) {
foreach (idx($id_map, $id, array()) as $name) {
$results[$name] = $object;
}
}
return $results;
}
}
diff --git a/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php b/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
index 388b6ab4d8..6703ed664e 100644
--- a/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
+++ b/src/applications/spaces/query/PhabricatorSpacesNamespaceQuery.php
@@ -1,238 +1,238 @@
<?php
final class PhabricatorSpacesNamespaceQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const KEY_ALL = 'spaces.all';
const KEY_DEFAULT = 'spaces.default';
const KEY_VIEWER = 'spaces.viewer';
private $ids;
private $phids;
private $isDefaultNamespace;
private $isArchived;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withIsDefaultNamespace($default) {
$this->isDefaultNamespace = $default;
return $this;
}
public function withIsArchived($archived) {
$this->isArchived = $archived;
return $this;
}
public function getQueryApplicationClass() {
- return 'PhabricatorSpacesApplication';
+ return PhabricatorSpacesApplication::class;
}
public function newResultObject() {
return new PhabricatorSpacesNamespace();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->isDefaultNamespace !== null) {
if ($this->isDefaultNamespace) {
$where[] = qsprintf(
$conn,
'isDefaultNamespace = 1');
} else {
$where[] = qsprintf(
$conn,
'isDefaultNamespace IS NULL');
}
}
if ($this->isArchived !== null) {
$where[] = qsprintf(
$conn,
'isArchived = %d',
(int)$this->isArchived);
}
return $where;
}
public static function destroySpacesCache() {
$cache = PhabricatorCaches::getRequestCache();
$cache->deleteKeys(
array(
self::KEY_ALL,
self::KEY_DEFAULT,
));
}
public static function getSpacesExist() {
return (bool)self::getAllSpaces();
}
public static function getViewerSpacesExist(PhabricatorUser $viewer) {
if (!self::getSpacesExist()) {
return false;
}
// If the viewer has access to only one space, pretend spaces simply don't
// exist.
$spaces = self::getViewerSpaces($viewer);
return (count($spaces) > 1);
}
public static function getAllSpaces() {
$cache = PhabricatorCaches::getRequestCache();
$cache_key = self::KEY_ALL;
$spaces = $cache->getKey($cache_key);
if ($spaces === null) {
$spaces = id(new PhabricatorSpacesNamespaceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->execute();
$spaces = mpull($spaces, null, 'getPHID');
$cache->setKey($cache_key, $spaces);
}
return $spaces;
}
public static function getDefaultSpace() {
$cache = PhabricatorCaches::getRequestCache();
$cache_key = self::KEY_DEFAULT;
$default_space = $cache->getKey($cache_key, false);
if ($default_space === false) {
$default_space = null;
$spaces = self::getAllSpaces();
foreach ($spaces as $space) {
if ($space->getIsDefaultNamespace()) {
$default_space = $space;
break;
}
}
$cache->setKey($cache_key, $default_space);
}
return $default_space;
}
public static function getViewerSpaces(PhabricatorUser $viewer) {
$cache = PhabricatorCaches::getRequestCache();
$cache_key = self::KEY_VIEWER.'('.$viewer->getCacheFragment().')';
$result = $cache->getKey($cache_key);
if ($result === null) {
$spaces = self::getAllSpaces();
$result = array();
foreach ($spaces as $key => $space) {
$can_see = PhabricatorPolicyFilter::hasCapability(
$viewer,
$space,
PhabricatorPolicyCapability::CAN_VIEW);
if ($can_see) {
$result[$key] = $space;
}
}
$cache->setKey($cache_key, $result);
}
return $result;
}
public static function getViewerActiveSpaces(PhabricatorUser $viewer) {
$spaces = self::getViewerSpaces($viewer);
foreach ($spaces as $key => $space) {
if ($space->getIsArchived()) {
unset($spaces[$key]);
}
}
return $spaces;
}
public static function getSpaceOptionsForViewer(
PhabricatorUser $viewer,
$space_phid) {
$viewer_spaces = self::getViewerSpaces($viewer);
$viewer_spaces = msort($viewer_spaces, 'getNamespaceName');
$map = array();
foreach ($viewer_spaces as $space) {
// Skip archived spaces, unless the object is already in that space.
if ($space->getIsArchived()) {
if ($space->getPHID() != $space_phid) {
continue;
}
}
$map[$space->getPHID()] = pht(
'Space %s: %s',
$space->getMonogram(),
$space->getNamespaceName());
}
return $map;
}
/**
* Get the Space PHID for an object, if one exists.
*
* This is intended to simplify performing a bunch of redundant checks; you
* can intentionally pass any value in (including `null`).
*
* @param wild
* @return phid|null
*/
public static function getObjectSpacePHID($object) {
if (!$object) {
return null;
}
if (!($object instanceof PhabricatorSpacesInterface)) {
return null;
}
$space_phid = $object->getSpacePHID();
if ($space_phid === null) {
$default_space = self::getDefaultSpace();
if ($default_space) {
$space_phid = $default_space->getPHID();
}
}
return $space_phid;
}
}
diff --git a/src/applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php b/src/applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php
index 3880143a24..835a5d596f 100644
--- a/src/applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php
+++ b/src/applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php
@@ -1,121 +1,121 @@
<?php
final class PhabricatorSpacesNamespaceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getApplicationClassName() {
- return 'PhabricatorSpacesApplication';
+ return PhabricatorSpacesApplication::class;
}
public function getResultTypeDescription() {
return pht('Spaces');
}
public function newQuery() {
return new PhabricatorSpacesNamespaceQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Active'))
->setKey('active')
->setOptions(
pht('(Show All)'),
pht('Show Only Active Spaces'),
pht('Hide Active Spaces')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['active']) {
$query->withIsArchived(!$map['active']);
}
return $query;
}
protected function getURI($path) {
return '/spaces/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'active' => pht('Active Spaces'),
'all' => pht('All Spaces'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'active':
return $query->setParameter('active', true);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $spaces,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($spaces, 'PhabricatorSpacesNamespace');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
$list->setUser($viewer);
foreach ($spaces as $space) {
$item = id(new PHUIObjectItemView())
->setObjectName($space->getMonogram())
->setHeader($space->getNamespaceName())
->setHref('/'.$space->getMonogram());
if ($space->getIsDefaultNamespace()) {
$item->addIcon('fa-certificate', pht('Default Space'));
}
if ($space->getIsArchived()) {
$item->setDisabled(true);
}
$list->addItem($item);
}
$result = new PhabricatorApplicationSearchResultView();
$result->setObjectList($list);
$result->setNoDataString(pht('No spaces found.'));
return $result;
}
protected function getNewUserBody() {
$create_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Create a Space'))
->setHref('/spaces/create/')
->setColor(PHUIButtonView::GREEN);
$icon = $this->getApplication()->getIcon();
$app_name = $this->getApplication()->getName();
$view = id(new PHUIBigInfoView())
->setIcon($icon)
->setTitle(pht('Welcome to %s', $app_name))
->setDescription(
pht('Policy namespaces to segment object visibility throughout your '.
'instance.'))
->addAction($create_button);
return $view;
}
}
diff --git a/src/applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php b/src/applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php
index 25951b53af..05008cd1fd 100644
--- a/src/applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php
+++ b/src/applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php
@@ -1,43 +1,43 @@
<?php
final class PhabricatorSpacesNamespaceDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Spaces');
}
public function getPlaceholderText() {
return pht('Type a space name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorSpacesApplication';
+ return PhabricatorSpacesApplication::class;
}
public function loadResults() {
$query = id(new PhabricatorSpacesNamespaceQuery());
$spaces = $this->executeQuery($query);
$results = array();
foreach ($spaces as $space) {
$full_name = pht(
'%s %s',
$space->getMonogram(),
$space->getNamespaceName());
$result = id(new PhabricatorTypeaheadResult())
->setName($full_name)
->setPHID($space->getPHID());
if ($space->getIsArchived()) {
$result->setClosed(pht('Archived'));
}
$results[] = $result;
}
return $this->filterResultsAgainstTokens($results);
}
}
diff --git a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php b/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php
index 93ff9500ac..0ff41cb4e5 100644
--- a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php
+++ b/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorTokenTokenPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'TOKN';
public function getTypeName() {
return pht('Token');
}
public function newObject() {
return new PhabricatorToken();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorTokensApplication';
+ return PhabricatorTokensApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorTokenQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$token = $objects[$phid];
$name = $token->getName();
$handle->setName(pht('%s Token', $name));
}
}
}
diff --git a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
index 14e8016cf1..63c23e12fb 100644
--- a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
@@ -1,126 +1,126 @@
<?php
final class PhabricatorTokenGivenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $authorPHIDs;
private $objectPHIDs;
private $tokenPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withTokenPHIDs(array $token_phids) {
$this->tokenPHIDs = $token_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function newResultObject() {
return new PhabricatorTokenGiven();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->tokenPHIDs !== null) {
$where[] = qsprintf(
$conn,
'tokenPHID IN (%Ls)',
$this->tokenPHIDs);
}
return $where;
}
protected function willFilterPage(array $results) {
$viewer = $this->getViewer();
$object_phids = mpull($results, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($results as $key => $result) {
$object = idx($objects, $result->getObjectPHID());
if ($object) {
if ($object instanceof PhabricatorTokenReceiverInterface) {
$result->attachObject($object);
continue;
}
}
$this->didRejectResult($result);
unset($results[$key]);
}
if (!$results) {
return $results;
}
$token_phids = mpull($results, 'getTokenPHID');
$tokens = id(new PhabricatorTokenQuery())
->setViewer($viewer)
->withPHIDs($token_phids)
->execute();
$tokens = mpull($tokens, null, 'getPHID');
foreach ($results as $key => $result) {
$token_phid = $result->getTokenPHID();
$token = idx($tokens, $token_phid);
if (!$token) {
$this->didRejectResult($result);
unset($results[$key]);
continue;
}
$result->attachToken($token);
}
return $results;
}
public function getQueryApplicationClass() {
- return 'PhabricatorTokensApplication';
+ return PhabricatorTokensApplication::class;
}
}
diff --git a/src/applications/tokens/query/PhabricatorTokenQuery.php b/src/applications/tokens/query/PhabricatorTokenQuery.php
index 07e15d4b03..f20bbebe1e 100644
--- a/src/applications/tokens/query/PhabricatorTokenQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenQuery.php
@@ -1,77 +1,77 @@
<?php
final class PhabricatorTokenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$tokens = $this->getBuiltinTokens();
if ($this->phids) {
$map = array_fill_keys($this->phids, true);
foreach ($tokens as $key => $token) {
if (empty($map[$token->getPHID()])) {
unset($tokens[$key]);
}
}
}
return $tokens;
}
private function getBuiltinTokens() {
$specs = array(
array('like-1', pht('Like')),
array('like-2', pht('Dislike')),
array('heart-1', pht('Love')),
array('heart-2', pht('Heartbreak')),
array('medal-1', pht('Orange Medal')),
array('medal-2', pht('Grey Medal')),
array('medal-3', pht('Yellow Medal')),
array('medal-4', pht('Manufacturing Defect?')),
array('coin-1', pht('Haypence')),
array('coin-2', pht('Piece of Eight')),
array('coin-3', pht('Doubloon')),
array('coin-4', pht('Mountain of Wealth')),
array('misc-1', pht('Pterodactyl')),
array('misc-2', pht('Evil Spooky Haunted Tree')),
array('misc-3', pht('Baby Tequila')),
array('misc-4', pht('The World Burns')),
array('emoji-1', pht('100')),
array('emoji-2', pht('Party Time')),
array('emoji-3', pht('Y So Serious')),
array('emoji-4', pht('Dat Boi')),
array('emoji-5', pht('Cup of Joe')),
array('emoji-6', pht('Hungry Hippo')),
array('emoji-7', pht('Burninate')),
array('emoji-8', pht('Pirate Logo')),
);
$type = PhabricatorTokenTokenPHIDType::TYPECONST;
$tokens = array();
foreach ($specs as $id => $spec) {
list($image, $name) = $spec;
$token = id(new PhabricatorToken())
->setID($id)
->setName($name)
->setPHID('PHID-'.$type.'-'.$image);
$tokens[] = $token;
}
return $tokens;
}
public function getQueryApplicationClass() {
- return 'PhabricatorTokensApplication';
+ return PhabricatorTokensApplication::class;
}
}
diff --git a/src/applications/tokens/query/PhabricatorTokenReceiverQuery.php b/src/applications/tokens/query/PhabricatorTokenReceiverQuery.php
index 2eb8158418..c1ba9f5998 100644
--- a/src/applications/tokens/query/PhabricatorTokenReceiverQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenReceiverQuery.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorTokenReceiverQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $tokenCounts;
protected function loadPage() {
$table = new PhabricatorTokenCount();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT objectPHID, tokenCount FROM %T ORDER BY tokenCount DESC',
$table->getTableName());
$this->tokenCounts = ipull($rows, 'tokenCount', 'objectPHID');
return ipull($rows, 'objectPHID');
}
protected function willFilterPage(array $phids) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($phids)
->execute();
// Reorder the objects in the input order.
$objects = array_select_keys($objects, $phids);
return $objects;
}
public function getTokenCounts() {
return $this->tokenCounts;
}
public function getQueryApplicationClass() {
- return 'PhabricatorTokensApplication';
+ return PhabricatorTokensApplication::class;
}
}
diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
index 5a30fbfdde..b95c31cc56 100644
--- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
+++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
@@ -1,114 +1,114 @@
<?php
final class PhabricatorEditEngineConfigurationEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'transactions.editengine.config';
private $targetEngine;
public function setTargetEngine(PhabricatorEditEngine $target_engine) {
$this->targetEngine = $target_engine;
return $this;
}
public function getTargetEngine() {
if (!$this->targetEngine) {
// If we don't have a target engine, assume we're editing ourselves.
return new PhabricatorEditEngineConfigurationEditEngine();
}
return $this->targetEngine;
}
protected function getCreateNewObjectPolicy() {
return $this->getTargetEngine()
->getApplication()
->getPolicy(PhabricatorPolicyCapability::CAN_EDIT);
}
public function getEngineName() {
return pht('Edit Configurations');
}
public function getSummaryHeader() {
return pht('Configure Forms for Configuring Forms');
}
public function getSummaryText() {
return pht(
'Change how forms in other applications are created and edited. '.
'Advanced!');
}
public function getEngineApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
protected function newEditableObject() {
return PhabricatorEditEngineConfiguration::initializeNewConfiguration(
$this->getViewer(),
$this->getTargetEngine());
}
protected function newObjectQuery() {
return id(new PhabricatorEditEngineConfigurationQuery());
}
protected function getObjectCreateTitleText($object) {
return pht('Create New Form');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Form %d: %s', $object->getID(), $object->getDisplayName());
}
protected function getObjectEditShortText($object) {
return pht('Form %d', $object->getID());
}
protected function getObjectCreateShortText() {
return pht('Create Form');
}
protected function getObjectName() {
return pht('Form');
}
protected function getObjectViewURI($object) {
$id = $object->getID();
return $this->getURI("view/{$id}/");
}
protected function getEditorURI() {
return $this->getURI('edit/');
}
protected function getObjectCreateCancelURI($object) {
return $this->getURI();
}
private function getURI($path = null) {
$engine_key = $this->getTargetEngine()->getEngineKey();
return "/transactions/editengine/{$engine_key}/{$path}";
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the form.'))
->setTransactionType(
PhabricatorEditEngineNameTransaction::TRANSACTIONTYPE)
->setValue($object->getName()),
id(new PhabricatorRemarkupEditField())
->setKey('preamble')
->setLabel(pht('Preamble'))
->setDescription(pht('Optional instructions, shown above the form.'))
->setTransactionType(
PhabricatorEditEnginePreambleTransaction::TRANSACTIONTYPE)
->setValue($object->getPreamble()),
);
}
}
diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
index 34b7653001..5229ee6bec 100644
--- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
+++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
@@ -1,21 +1,21 @@
<?php
final class PhabricatorEditEngineConfigurationEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Edit Configurations');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
return $types;
}
}
diff --git a/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php b/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php
index e6184b1ae4..796f68e2cc 100644
--- a/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php
+++ b/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php
@@ -1,92 +1,92 @@
<?php
final class PhabricatorApplicationTransactionTransactionPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'XACT';
public function getTypeName() {
return pht('Transaction');
}
public function newObject() {
// NOTE: We could produce an object here, but we'd need to take a PHID type
// and subtype to do so. Currently, we never write edges to transactions,
// so leave this unimplemented for the moment.
return null;
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
throw new Exception();
}
public function loadObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
static $queries;
if ($queries === null) {
$objects = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationTransactionQuery')
->execute();
$queries = array();
foreach ($objects as $object) {
$type = $object
->getTemplateApplicationTransaction()
->getApplicationTransactionType();
$queries[$type] = $object;
}
}
$phid_subtypes = array();
foreach ($phids as $phid) {
$subtype = phid_get_subtype($phid);
if ($subtype) {
$phid_subtypes[$subtype][] = $phid;
}
}
$results = array();
foreach ($phid_subtypes as $subtype => $subtype_phids) {
$query = idx($queries, $subtype);
if (!$query) {
continue;
}
$xaction_query = id(clone $query)
->setViewer($object_query->getViewer())
->setParentQuery($object_query)
->withPHIDs($subtype_phids);
if (!$xaction_query->canViewerUseQueryApplication()) {
$object_query->addPolicyFilteredPHIDs(array_fuse($subtype_phids));
continue;
}
$xactions = $xaction_query->execute();
$results += mpull($xactions, null, 'getPHID');
}
return $results;
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
// NOTE: We don't produce meaningful handles here because they're
// impractical to produce and no application uses them.
}
}
diff --git a/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php b/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php
index b4ac0ddbfe..d10446e6eb 100644
--- a/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php
+++ b/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php
@@ -1,43 +1,43 @@
<?php
final class PhabricatorEditEngineConfigurationPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'FORM';
public function getTypeName() {
return pht('Edit Configuration');
}
public function newObject() {
return new PhabricatorEditEngineConfiguration();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
return id(new PhabricatorEditEngineConfigurationQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$config = $objects[$phid];
$id = $config->getID();
$name = $config->getName();
$handle->setName($name);
$handle->setURI($config->getURI());
}
}
}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php
index d2cbc3e697..d29fd10873 100644
--- a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php
+++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php
@@ -1,284 +1,284 @@
<?php
final class PhabricatorEditEngineConfigurationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $engineKeys;
private $builtinKeys;
private $identifiers;
private $default;
private $isEdit;
private $disabled;
private $ignoreDatabaseConfigurations;
private $subtypes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withEngineKeys(array $engine_keys) {
$this->engineKeys = $engine_keys;
return $this;
}
public function withBuiltinKeys(array $builtin_keys) {
$this->builtinKeys = $builtin_keys;
return $this;
}
public function withIdentifiers(array $identifiers) {
$this->identifiers = $identifiers;
return $this;
}
public function withIsDefault($default) {
$this->default = $default;
return $this;
}
public function withIsEdit($edit) {
$this->isEdit = $edit;
return $this;
}
public function withIsDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function withIgnoreDatabaseConfigurations($ignore) {
$this->ignoreDatabaseConfigurations = $ignore;
return $this;
}
public function withSubtypes(array $subtypes) {
$this->subtypes = $subtypes;
return $this;
}
public function newResultObject() {
return new PhabricatorEditEngineConfiguration();
}
protected function loadPage() {
// TODO: The logic here is a little flimsy and won't survive pagination.
// For now, I'm just not bothering with pagination since I believe it will
// take some time before any install manages to produce a large enough
// number of edit forms for any particular engine for the lack of UI
// pagination to become a problem.
if ($this->ignoreDatabaseConfigurations) {
$page = array();
} else {
$page = $this->loadStandardPage($this->newResultObject());
}
// Now that we've loaded the real results from the database, we're going
// to load builtins from the edit engines and add them to the list.
$engines = PhabricatorEditEngine::getAllEditEngines();
if ($this->engineKeys) {
$engines = array_select_keys($engines, $this->engineKeys);
}
foreach ($engines as $engine) {
$engine->setViewer($this->getViewer());
}
// List all the builtins which have already been saved to the database as
// real objects.
$concrete = array();
foreach ($page as $config) {
$builtin_key = $config->getBuiltinKey();
if ($builtin_key !== null) {
$engine_key = $config->getEngineKey();
$concrete[$engine_key][$builtin_key] = $config;
}
}
$builtins = array();
foreach ($engines as $engine_key => $engine) {
$engine_builtins = $engine->getBuiltinEngineConfigurations();
foreach ($engine_builtins as $engine_builtin) {
$builtin_key = $engine_builtin->getBuiltinKey();
if (isset($concrete[$engine_key][$builtin_key])) {
continue;
} else {
$builtins[] = $engine_builtin;
}
}
}
foreach ($builtins as $builtin) {
$page[] = $builtin;
}
// Now we have to do some extra filtering to make sure everything we're
// about to return really satisfies the query.
if ($this->ids !== null) {
$ids = array_fuse($this->ids);
foreach ($page as $key => $config) {
if (empty($ids[$config->getID()])) {
unset($page[$key]);
}
}
}
if ($this->phids !== null) {
$phids = array_fuse($this->phids);
foreach ($page as $key => $config) {
if (empty($phids[$config->getPHID()])) {
unset($page[$key]);
}
}
}
if ($this->builtinKeys !== null) {
$builtin_keys = array_fuse($this->builtinKeys);
foreach ($page as $key => $config) {
if (empty($builtin_keys[$config->getBuiltinKey()])) {
unset($page[$key]);
}
}
}
if ($this->default !== null) {
foreach ($page as $key => $config) {
if ($config->getIsDefault() != $this->default) {
unset($page[$key]);
}
}
}
if ($this->isEdit !== null) {
foreach ($page as $key => $config) {
if ($config->getIsEdit() != $this->isEdit) {
unset($page[$key]);
}
}
}
if ($this->disabled !== null) {
foreach ($page as $key => $config) {
if ($config->getIsDisabled() != $this->disabled) {
unset($page[$key]);
}
}
}
if ($this->identifiers !== null) {
$identifiers = array_fuse($this->identifiers);
foreach ($page as $key => $config) {
if (isset($identifiers[$config->getBuiltinKey()])) {
continue;
}
if (isset($identifiers[$config->getID()])) {
continue;
}
unset($page[$key]);
}
}
if ($this->subtypes !== null) {
$subtypes = array_fuse($this->subtypes);
foreach ($page as $key => $config) {
if (isset($subtypes[$config->getSubtype()])) {
continue;
}
unset($page[$key]);
}
}
return $page;
}
protected function willFilterPage(array $configs) {
$engine_keys = mpull($configs, 'getEngineKey');
$engines = id(new PhabricatorEditEngineQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withEngineKeys($engine_keys)
->execute();
$engines = mpull($engines, null, 'getEngineKey');
foreach ($configs as $key => $config) {
$engine = idx($engines, $config->getEngineKey());
if (!$engine) {
$this->didRejectResult($config);
unset($configs[$key]);
continue;
}
$config->attachEngine($engine);
}
return $configs;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->engineKeys !== null) {
$where[] = qsprintf(
$conn,
'engineKey IN (%Ls)',
$this->engineKeys);
}
if ($this->builtinKeys !== null) {
$where[] = qsprintf(
$conn,
'builtinKey IN (%Ls)',
$this->builtinKeys);
}
if ($this->identifiers !== null) {
$where[] = qsprintf(
$conn,
'(id IN (%Ls) OR builtinKey IN (%Ls))',
$this->identifiers,
$this->identifiers);
}
if ($this->subtypes !== null) {
$where[] = qsprintf(
$conn,
'subtype IN (%Ls)',
$this->subtypes);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php
index 694b4c48b6..c74ba38713 100644
--- a/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php
+++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php
@@ -1,165 +1,165 @@
<?php
final class PhabricatorEditEngineConfigurationSearchEngine
extends PhabricatorApplicationSearchEngine {
private $engineKey;
public function setEngineKey($engine_key) {
$this->engineKey = $engine_key;
return $this;
}
public function getEngineKey() {
return $this->engineKey;
}
public function canUseInPanelContext() {
return false;
}
public function getResultTypeDescription() {
return pht('Forms');
}
public function getApplicationClassName() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
public function newQuery() {
return id(new PhabricatorEditEngineConfigurationQuery())
->withEngineKeys(array($this->getEngineKey()));
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
$is_create = $map['isCreate'];
if ($is_create !== null) {
$query->withIsDefault($is_create);
}
$is_edit = $map['isEdit'];
if ($is_edit !== null) {
$query->withIsEdit($is_edit);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Create'))
->setKey('isCreate')
->setOptions(
pht('Show All'),
pht('Hide Create Forms'),
pht('Show Only Create Forms')),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Edit'))
->setKey('isEdit')
->setOptions(
pht('Show All'),
pht('Hide Edit Forms'),
pht('Show Only Edit Forms')),
);
}
protected function getDefaultFieldOrder() {
return array();
}
protected function getURI($path) {
return '/transactions/editengine/'.$this->getEngineKey().'/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Forms'),
'create' => pht('Create Forms'),
'modify' => pht('Edit Forms'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'create':
return $query->setParameter('isCreate', true);
case 'modify':
return $query->setParameter('isEdit', true);
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $configs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($configs, 'PhabricatorEditEngineConfiguration');
$viewer = $this->requireViewer();
$engine_key = $this->getEngineKey();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($configs as $config) {
$item = id(new PHUIObjectItemView())
->setHeader($config->getDisplayName());
$id = $config->getID();
if ($config->getIsDefault()) {
$item->addAttribute(pht('Default Create Form'));
}
if ($config->getIsEdit()) {
$item->addAttribute(pht('Edit Form'));
}
if ($config->getIsDisabled()) {
$item->setDisabled(true);
$item->setStatusIcon('fa-ban grey', pht('Disabled'));
} else {
$item->setStatusIcon('fa-file-text-o green', pht('Enabled'));
}
$subtype_key = $config->getSubtype();
if ($subtype_key !== PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT) {
$engine = $config->getEngine();
if ($engine->supportsSubtypes()) {
$map = $engine->newSubtypeMap();
if ($map->isValidSubtype($subtype_key)) {
$subtype = $map->getSubtype($subtype_key);
$icon = $subtype->getIcon();
$color = $subtype->getColor();
$item->addIcon("{$icon} {$color}", $subtype->getName());
}
}
}
if ($id) {
$item->setObjectName(pht('Form %d', $id));
$key = $id;
} else {
$item->addIcon('fa-file-text bluegrey', pht('Builtin'));
$key = $config->getBuiltinKey();
}
$item->setHref("/transactions/editengine/{$engine_key}/view/{$key}/");
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list);
}
}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineQuery.php b/src/applications/transactions/query/PhabricatorEditEngineQuery.php
index 400b62a487..48295ab31c 100644
--- a/src/applications/transactions/query/PhabricatorEditEngineQuery.php
+++ b/src/applications/transactions/query/PhabricatorEditEngineQuery.php
@@ -1,49 +1,49 @@
<?php
final class PhabricatorEditEngineQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $engineKeys;
public function withEngineKeys(array $keys) {
$this->engineKeys = $keys;
return $this;
}
protected function loadPage() {
$engines = PhabricatorEditEngine::getAllEditEngines();
if ($this->engineKeys !== null) {
$engines = array_select_keys($engines, $this->engineKeys);
}
return $engines;
}
protected function willFilterPage(array $engines) {
$viewer = $this->getViewer();
foreach ($engines as $key => $engine) {
$app_class = $engine->getEngineApplicationClass();
if ($app_class === null) {
continue;
}
$can_see = PhabricatorApplication::isClassInstalledForViewer(
$app_class,
$viewer);
if (!$can_see) {
$this->didRejectResult($engine);
unset($engines[$key]);
continue;
}
}
return $engines;
}
public function getQueryApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php b/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php
index 4ba1a0e879..822548f860 100644
--- a/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php
+++ b/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php
@@ -1,91 +1,91 @@
<?php
final class PhabricatorEditEngineSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Edit Engines');
}
public function getApplicationClassName() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
public function newQuery() {
return id(new PhabricatorEditEngineQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getDefaultFieldOrder() {
return array();
}
protected function getURI($path) {
return '/transactions/editengine/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Edit Engines'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $engines,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($engines, 'PhabricatorEditEngine');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($engines as $engine) {
if (!$engine->isEngineConfigurable()) {
continue;
}
$engine_key = $engine->getEngineKey();
$query_uri = "/transactions/editengine/{$engine_key}/";
$application = $engine->getApplication();
$app_icon = $application->getIcon();
$item = id(new PHUIObjectItemView())
->setHeader($engine->getSummaryHeader())
->setHref($query_uri)
->setStatusIcon($app_icon)
->addAttribute($engine->getSummaryText());
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setObjectList($list);
}
}
diff --git a/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php
index 6520ca6732..74771ee834 100644
--- a/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php
+++ b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php
@@ -1,67 +1,67 @@
<?php
final class PhabricatorEditEngineDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Forms');
}
public function getPlaceholderText() {
return pht('Type a form name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
private function buildResults() {
$query = id(new PhabricatorEditEngineConfigurationQuery());
$forms = $this->executeQuery($query);
$results = array();
foreach ($forms as $form) {
$create_uri = $form->getCreateURI();
if (!$create_uri) {
continue;
}
if ($form->getID()) {
$key = $form->getEngineKey().'/'.$form->getID();
} else {
$key = $form->getEngineKey().'/'.$form->getBuiltinKey();
}
$result = id(new PhabricatorTypeaheadResult())
->setName($form->getName())
->setPHID($key)
->setIcon($form->getIcon());
if ($form->getIsDisabled()) {
$result->setClosed(pht('Archived'));
}
if ($form->getIsDefault()) {
$result->addAttribute(pht('Create Form'));
}
if ($form->getIsEdit()) {
$result->addAttribute(pht('Edit Form'));
}
$results[$key] = $result;
}
return $results;
}
}
diff --git a/src/applications/transactions/typeahead/PhabricatorTransactionsObjectTypeDatasource.php b/src/applications/transactions/typeahead/PhabricatorTransactionsObjectTypeDatasource.php
index e7292fc522..d515b8303a 100644
--- a/src/applications/transactions/typeahead/PhabricatorTransactionsObjectTypeDatasource.php
+++ b/src/applications/transactions/typeahead/PhabricatorTransactionsObjectTypeDatasource.php
@@ -1,63 +1,63 @@
<?php
final class PhabricatorTransactionsObjectTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Forms');
}
public function getPlaceholderText() {
return pht('Type an object type name...');
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorTransactionsApplication';
+ return PhabricatorTransactionsApplication::class;
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
private function buildResults() {
$queries = id(new PhutilClassMapQuery())
->setAncestorClass('PhabricatorApplicationTransactionQuery')
->execute();
$phid_types = PhabricatorPHIDType::getAllTypes();
$results = array();
foreach ($queries as $query) {
$query_type = $query->getTemplateApplicationTransaction()
->getApplicationTransactionType();
$phid_type = idx($phid_types, $query_type);
if ($phid_type) {
$name = $phid_type->getTypeName();
$icon = $phid_type->getTypeIcon();
} else {
$name = pht('%s ("%s")', $query_type, get_class($query));
$icon = null;
}
$result = id(new PhabricatorTypeaheadResult())
->setName($name)
->setPHID($query_type);
if ($icon) {
$result->setIcon($icon);
}
$results[$query_type] = $result;
}
return $results;
}
}
diff --git a/src/applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.php b/src/applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.php
index f16a64bb9b..ae5c87b45c 100644
--- a/src/applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.php
+++ b/src/applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.php
@@ -1,67 +1,67 @@
<?php
final class PhabricatorTypeaheadTestNumbersDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Numbers');
}
public function getPlaceholderText() {
return null;
}
public function getDatasourceApplicationClass() {
- return 'PhabricatorPeopleApplication';
+ return PhabricatorPeopleApplication::class;
}
public function getDatasourceFunctions() {
return array(
'seven' => array(),
'inc' => array(),
'sum' => array(),
);
}
public function loadResults() {
return array();
}
public function renderFunctionTokens($function, array $argv_list) {
return array();
}
protected function evaluateFunction($function, array $argv_list) {
$results = array();
foreach ($argv_list as $argv) {
foreach ($argv as $k => $arg) {
if (!is_scalar($arg) || !preg_match('/^\d+\z/', $arg)) {
throw new PhabricatorTypeaheadInvalidTokenException(
pht(
'All arguments to "%s(...)" must be integers, found '.
'"%s" in position %d.',
$function,
(is_scalar($arg) ? $arg : gettype($arg)),
$k + 1));
}
$argv[$k] = (int)$arg;
}
switch ($function) {
case 'seven':
$results[] = 7;
break;
case 'inc':
$results[] = $argv[0] + 1;
break;
case 'sum':
$results[] = array_sum($argv);
break;
}
}
return $results;
}
}
diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
index 2001fec0c7..2160507a53 100644
--- a/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
+++ b/src/applications/xhprof/query/PhabricatorXHProfSampleQuery.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorXHProfSampleQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorXHProfSample();
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorXHProfApplication';
+ return PhabricatorXHProfApplication::class;
}
}
diff --git a/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php
index 171f28f027..f0a5273f3e 100644
--- a/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php
+++ b/src/applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.php
@@ -1,120 +1,120 @@
<?php
final class PhabricatorXHProfSampleSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('XHProf Samples');
}
public function getApplicationClassName() {
- return 'PhabricatorXHProfApplication';
+ return PhabricatorXHProfApplication::class;
}
public function newQuery() {
return id(new PhabricatorXHProfSampleQuery());
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
return $query;
}
protected function buildCustomSearchFields() {
return array();
}
protected function getURI($path) {
return '/xhprof/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Samples'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $samples,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($samples, 'PhabricatorXHProfSample');
$viewer = $this->requireViewer();
$list = new PHUIObjectItemListView();
foreach ($samples as $sample) {
$file_phid = $sample->getFilePHID();
$item = id(new PHUIObjectItemView())
->setObjectName($sample->getID())
->setHeader($sample->getDisplayName())
->setHref($sample->getURI());
$us_total = $sample->getUsTotal();
if ($us_total) {
$item->addAttribute(pht("%s \xCE\xBCs", new PhutilNumber($us_total)));
}
if ($sample->getController()) {
$item->addAttribute($sample->getController());
}
$item->addAttribute($sample->getHostName());
$rate = $sample->getSampleRate();
if ($rate == 0) {
$item->addIcon('flag-6', pht('Manual Run'));
} else {
$item->addIcon('flag-7', pht('Sampled (1/%d)', $rate));
}
$item->addIcon(
'none',
phabricator_datetime($sample->getDateCreated(), $viewer));
$list->addItem($item);
}
return $this->newResultView()
->setObjectList($list);
}
private function newResultView($content = null) {
// If we aren't rendering a dashboard panel, activate global drag-and-drop
// so you can import profiles by dropping them into the list.
if (!$this->isPanelContext()) {
$drop_upload = id(new PhabricatorGlobalUploadTargetView())
->setViewer($this->requireViewer())
->setHintText("\xE2\x87\xAA ".pht('Drop .xhprof Files to Import'))
->setSubmitURI('/xhprof/import/drop/')
->setViewPolicy(PhabricatorPolicies::POLICY_NOONE);
$content = array(
$drop_upload,
$content,
);
}
return id(new PhabricatorApplicationSearchResultView())
->setContent($content);
}
}
diff --git a/src/infrastructure/daemon/workers/editor/PhabricatorWorkerBulkJobEditor.php b/src/infrastructure/daemon/workers/editor/PhabricatorWorkerBulkJobEditor.php
index e94ca6dc49..bd4a271fc7 100644
--- a/src/infrastructure/daemon/workers/editor/PhabricatorWorkerBulkJobEditor.php
+++ b/src/infrastructure/daemon/workers/editor/PhabricatorWorkerBulkJobEditor.php
@@ -1,88 +1,88 @@
<?php
final class PhabricatorWorkerBulkJobEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
public function getEditorObjectsDescription() {
return pht('Bulk Jobs');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorWorkerBulkJobTransaction::TYPE_STATUS;
$types[] = PhabricatorTransactions::TYPE_EDGE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorWorkerBulkJobTransaction::TYPE_STATUS:
return $object->getStatus();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorWorkerBulkJobTransaction::TYPE_STATUS:
return $xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$type = $xaction->getTransactionType();
$new = $xaction->getNewValue();
switch ($type) {
case PhabricatorWorkerBulkJobTransaction::TYPE_STATUS:
$object->setStatus($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$type = $xaction->getTransactionType();
$new = $xaction->getNewValue();
switch ($type) {
case PhabricatorWorkerBulkJobTransaction::TYPE_STATUS:
switch ($new) {
case PhabricatorWorkerBulkJob::STATUS_WAITING:
PhabricatorWorker::scheduleTask(
'PhabricatorWorkerBulkJobCreateWorker',
array(
'jobID' => $object->getID(),
),
array(
'priority' => PhabricatorWorker::PRIORITY_BULK,
));
break;
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
}
diff --git a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php
index b94f7eab27..d3d672897a 100644
--- a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php
+++ b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorWorkerBulkJobPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'BULK';
public function getTypeName() {
return pht('Bulk Job');
}
public function newObject() {
return new PhabricatorWorkerBulkJob();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorWorkerBulkJobQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$job = $objects[$phid];
$id = $job->getID();
$handle->setName(pht('Bulk Job %d', $id));
}
}
}
diff --git a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php
index b1dadb568e..c301e3d2be 100644
--- a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php
+++ b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php
@@ -1,41 +1,41 @@
<?php
final class PhabricatorWorkerTriggerPHIDType extends PhabricatorPHIDType {
const TYPECONST = 'TRIG';
public function getTypeName() {
return pht('Trigger');
}
public function newObject() {
return new PhabricatorWorkerTrigger();
}
public function getPHIDTypeApplicationClass() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorWorkerTriggerQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$trigger = $objects[$phid];
$id = $trigger->getID();
$handle->setName(pht('Trigger %d', $id));
}
}
}
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
index b359157e06..bdedc3584c 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php
@@ -1,102 +1,102 @@
<?php
final class PhabricatorWorkerBulkJobQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $bulkJobTypes;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withBulkJobTypes(array $job_types) {
$this->bulkJobTypes = $job_types;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function newResultObject() {
return new PhabricatorWorkerBulkJob();
}
protected function willFilterPage(array $page) {
$map = PhabricatorWorkerBulkJobType::getAllJobTypes();
foreach ($page as $key => $job) {
$implementation = idx($map, $job->getJobTypeKey());
if (!$implementation) {
$this->didRejectResult($job);
unset($page[$key]);
continue;
}
$job->attachJobImplementation($implementation);
}
return $page;
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
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->authorPHIDs !== null) {
$where[] = qsprintf(
$conn,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->bulkJobTypes !== null) {
$where[] = qsprintf(
$conn,
'bulkJobType IN (%Ls)',
$this->bulkJobTypes);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
return $where;
}
public function getQueryApplicationClass() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
}
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobSearchEngine.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobSearchEngine.php
index 3b9d6c9d48..cda4176f29 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobSearchEngine.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobSearchEngine.php
@@ -1,101 +1,101 @@
<?php
final class PhabricatorWorkerBulkJobSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Daemon Bulk Jobs');
}
public function getApplicationClassName() {
- return 'PhabricatorDaemonsApplication';
+ return PhabricatorDaemonsApplication::class;
}
public function newQuery() {
return id(new PhabricatorWorkerBulkJobQuery());
}
public function canUseInPanelContext() {
return false;
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['authorPHIDs']) {
$query->withAuthorPHIDs($map['authorPHIDs']);
}
return $query;
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorUsersSearchField())
->setLabel(pht('Authors'))
->setKey('authorPHIDs')
->setAliases(array('author', 'authors')),
);
}
protected function getURI($path) {
return '/daemon/bulk/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['authored'] = pht('Authored Jobs');
}
$names['all'] = pht('All Jobs');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
case 'authored':
return $query->setParameter(
'authorPHIDs',
array($this->requireViewer()->getPHID()));
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $jobs,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($jobs, 'PhabricatorWorkerBulkJob');
$viewer = $this->requireViewer();
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($jobs as $job) {
$size = pht('%s Bulk Task(s)', new PhutilNumber($job->getSize()));
$item = id(new PHUIObjectItemView())
->setObjectName(pht('Bulk Job %d', $job->getID()))
->setHeader($job->getJobName())
->addAttribute(phabricator_datetime($job->getDateCreated(), $viewer))
->setHref($job->getManageURI())
->addIcon($job->getStatusIcon(), $job->getStatusName())
->addIcon('none', $size);
$list->addItem($item);
}
return id(new PhabricatorApplicationSearchResultView())
->setContent($list);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 4:34 PM (1 d, 9 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
38/3b/5a66c8c5e61f8f845858dd731559
Default Alt Text
(2 MB)

Event Timeline