Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3766162
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/app/Phabricator/PhabricatorStory.php b/app/Phabricator/PhabricatorStory.php
index 83c455d..f15a073 100644
--- a/app/Phabricator/PhabricatorStory.php
+++ b/app/Phabricator/PhabricatorStory.php
@@ -1,271 +1,271 @@
<?php
namespace Nasqueron\Notifications\Phabricator;
class PhabricatorStory {
///
/// Properties
///
/**
* The Phabricator main URL
*
* @var string
*/
public $instance;
/**
* The unique identifier Phabricator assigns to each story
*
* @var int
*/
public $id;
/**
* Type of story (e.g. PhabricatorApplicationTransactionFeedStory)
*
* @var string
*/
public $type;
/**
- * @var Array
+ * @var array
*/
public $data;
/**
* The person logged to Phabricator and triggering the event
*
* @var string
*/
public $authorPHID;
/**
* A short English textual description of the event
*
* @var string
*/
public $text;
/**
* The unixtime the event occured
*
* @var int
*/
public $epoch;
/**
* The projects attached to this story.
*
* When there is no project, [].
* When not yet queried, null.
*
* @var string[]|null
*/
private $projects = null;
///
/// Constructors
///
/**
* Initializes a new instance of the Phabricator story class
*
* @param string $instance The Phabricator main URL, without trailing slash
*/
public function __construct ($instance) {
$this->instance = $instance;
}
/**
* Initializes a new instance of PhabricatorStory from an array.
*
* This is intended to parse the feed.hooks payloads.
*
* @param string $phabricatorURL The Phabricator URL (e.g. http://secure.phabricator.com)
* @param string $payload The data submitted by Phabricator
* @return PhabricatorStory
*/
public static function loadFromArray ($phabricatorURL, $payload) {
$instance = new self($phabricatorURL);
foreach ($payload as $key => $value) {
$property = self::mapPhabricatorFeedKey($key);
$instance->$property = $value;
}
return $instance;
}
///
/// Helper methods
///
/**
* Gets object type (e.g. TASK for PHID-TASK-l34fw5wievp6n6rnvpuk)
*
* @return string The object type, as a 4 letters string (e.g. 'TASK')
*/
public function getObjectType () {
return substr($this->data['objectPHID'], 5, 4);
}
/**
* Gets the identifier of the projets related to this task
*
* return string[] The list of project PHIDs
*/
public function getProjectsPHIDs () {
$objectPHID = $this->data['objectPHID'];
$objectType = $this->getObjectType();
switch ($objectType) {
case 'DREV':
return $this->getItemProjectsPHIDs(
'repository.query',
$this->getRepositoryPHID('differential.query')
);
case 'TASK':
return $this->getItemProjectsPHIDs(
'maniphest.query',
$objectPHID
);
case 'CMIT':
return $this->getItemProjectsPHIDs(
'repository.query',
$this->getRepositoryPHID('diffusion.querycommits')
);
case 'PSTE':
return $this->getItemProjectsPHIDsThroughApplicationSearch(
'paste.search',
$objectPHID
);
default:
return [];
}
}
/**
* Gets the PHID of a repository
*
* @param string $method The API method to call (e.g. differential.query)
* @return string The repository PHID or "" if not found
*/
public function getRepositoryPHID ($method) {
$objectPHID = $this->data['objectPHID'];
$api = PhabricatorAPI::forInstance($this->instance);
$reply = $api->call(
$method,
[ 'phids[0]' => $objectPHID ]
);
return PhabricatorAPI::getFirstResult($reply)->repositoryPHID;
}
/**
* Gets the projects for a specific item
*
* @param string $method The API method to call (e.g. differential.query)
* @param string $objectPHID The object PHID to pass as method parameter
* @return string[] The list of project PHIDs
*/
public function getItemProjectsPHIDs ($method, $objectPHID) {
if (!$objectPHID) {
return [];
}
$api = PhabricatorAPI::forInstance($this->instance);
$reply = $api->call(
$method,
[ 'phids[0]' => $objectPHID ]
);
return PhabricatorAPI::getFirstResult($reply)->projectPHIDs;
}
/**
* Gets the project for a specific item, using the new ApplicationSearch.
*
* This is a transitional method: when every Phabricator will have been
* migrated from info (generation 1) or query (generation 2) to search
* (generation 3), we'll rename it to getItemProjectsPHIDs and overwrite it.
*/
protected function getItemProjectsPHIDsThroughApplicationSearch ($method, $objectPHID) {
if (!$objectPHID) {
return [];
}
$api = PhabricatorAPI::forInstance($this->instance);
$reply = $api->call(
$method,
[
'constraints[phids][0]' => $objectPHID,
'attachments[projects]' => 1
]
);
return PhabricatorAPI::getFirstResult($reply)->attachments->projects->projectPHIDs;
}
/**
* Gets the list of the projects associated to the story
*
* @return string[] The list of project PHIDs
*/
public function getProjects () {
if ($this->projects === null) {
$this->attachProjects();
}
return $this->projects;
}
/**
* Queries the list of the projects associated to the story
* and attached it to the projects property.
*/
public function attachProjects () {
$this->projects = [];
$PHIDs = $this->getProjectsPHIDs();
if (count($PHIDs) == 0) {
// No project is attached to the story's object
return;
}
$map = ProjectsMap::load($this->instance);
foreach ($PHIDs as $PHID) {
$this->projects[] = $map->getProjectName($PHID);
}
}
///
/// Static helper methods
///
/**
* Maps a field of the API reply to a property of the PhabricatorStory class
*
* @param string $key The field of the API reply
* @return string The property's name
*/
public static function mapPhabricatorFeedKey ($key) {
if ($key == "storyID") {
return "id";
}
if (starts_with($key, "story")) {
$key = substr($key, 5);
$key[0] = strtolower($key[0]); // lowercase
}
return $key;
}
}
diff --git a/app/Phabricator/ProjectsMap.php b/app/Phabricator/ProjectsMap.php
index 228cbbe..9688eb4 100644
--- a/app/Phabricator/ProjectsMap.php
+++ b/app/Phabricator/ProjectsMap.php
@@ -1,226 +1,242 @@
<?php
namespace Nasqueron\Notifications\Phabricator;
use Cache;
class ProjectsMap implements \IteratorAggregate, \ArrayAccess {
///
/// Private properties and constants
/**
* The maximum number of projects to fetch
*/
const LIMIT = 1000;
/**
* The projects as an array with phid as keys, project names as $value
*
* @var string[]
*/
private $map = [];
/**
* The Phabricator instance for this projects map
*
* @var string
*/
private $instance;
/**
* The source of the map
*
* @var string
*/
private $source = 'unloaded';
///
/// Constructor
///
/**
* Initializes a new instance of ProjectsMap
*
* @param string $instance The Phabricator root URL without trailing slash
*/
public function __construct ($instance) {
$this->instance = $instance;
}
///
/// IteratorAggregate interface implementation
///
/**
* Gets iterator
*
* @return Traversable
*/
public function getIterator ( ) {
return new ArrayIterator($this->map);
}
///
/// ArrayAccess interface implementation
///
/**
* Determines whether an offset exists
*
* @param mixed $offset The offset
*/
public function offsetExists ($offset) {
return array_key_exists($offset, $this->map);
}
/**
* Gets an offset
*
* @param mixed $offset The offset
* @return mixed The value
*/
public function offsetGet ($offset) {
return $this->map[$offset];
}
/**
* Assigns a value to the specified offset
*
* @param mixed $offset The offset
* @param mixed $value The value to assign
*/
public function offsetSet ($offset, $value) {
$this->map[$offset] = $value;
}
/**
* Unset an offset
*
* @param mixed $offset The offset
*/
public function offsetUnset ($offset) {
unset($this->map[$offset]);
}
///
/// Static constructors
///
/**
* Gets a new ProjectsMap instance from cache or API when not cached
*
* @param string $phabricatorURL The Phabricator URL (e.g. http://secure.phabricator.com)
* @return ProjectsMap
*/
public static function load ($phabricatorURL) {
$instance = new self($phabricatorURL);
if ($instance->isCached()) {
$instance->loadFromCache();
} else {
$instance->fetchFromAPI();
}
return $instance;
}
/**
- * Gets a new ProjectsMap instance and queries Phabricator API to fill it.
+ * Gets a new ProjectsMap instance and queries Phabricator API to fill it
*
* @param string $phabricatorURL The Phabricator URL (e.g. http://secure.phabricator.com)
* @return ProjectsMap
*/
public static function fetch ($phabricatorURL) {
$instance = new self($phabricatorURL);
$instance->fetchFromAPI();
return $instance;
}
///
/// API
///
- public function fetchFromAPI () {
+ /**
+ * Fetches the projects' map from the Phabricator API
+ */
+ private function fetchFromAPI () {
$reply = PhabricatorAPI::forInstance($this->instance)->call(
'project.query',
[ 'limit' => self::LIMIT ]
);
if (!$reply) {
throw new \Exception("Empty reply calling project.query at $this->instance API.");
}
if (!property_exists($reply, 'data')) {
throw new \Exception("Invalid reply calling project.query at $this->instance API.");
}
foreach ($reply->data as $phid => $projectInfo) {
$this->offsetSet($phid, $projectInfo->name);
}
$this->source = 'api';
}
///
/// Cache
///
/**
* Gets cache key
*
* @return string The cache key for the current projects map
*/
private function getCacheKey () {
return class_basename(get_class($this)) . '-' . md5($this->instance);
}
- public function isCached () {
+ /**
+ * Determines if the instance is cached
+ *
+ * @return bool true if cached; otherwise, false.
+ */
+ private function isCached () {
return Cache::has($this->getCacheKey());
}
+ /**
+ * Saves data to cache
+ */
public function saveToCache () {
Cache::forever($this->getCacheKey(), $this->map);
}
+ /**
+ * Loads data from cache
+ *
+ * Populates 'map' and 'source' properties
+ */
public function loadFromCache () {
$this->map = Cache::get($this->getCacheKey());
$this->source = 'cache';
}
///
/// Output
///
/**
* Gets project name, refreshing the cache if needed
*
* @param string $projectPHID the PHID of the project to query the name
* @return string
*/
public function getProjectName ($projectPHID) {
if ($this->offsetExists($projectPHID)) {
return $this->offsetGet($projectPHID);
}
if ($this->source !== 'api') {
$this->fetchFromAPI();
return $this->getProjectName($projectPHID);
}
return "";
}
/**
* Returns the projects map as an array, each row ['PHID', 'project name']
*
- * @return Array
+ * @return array
*/
public function toArray () {
$array = [];
foreach ($this->map as $phid => $projectName) {
$array[] = [$phid, $projectName];
}
return $array;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Nov 24, 16:46 (7 m, 12 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2258460
Default Alt Text
(13 KB)
Attached To
Mode
rNOTIF Notifications center
Attached
Detach File
Event Timeline
Log In to Comment