Page MenuHomeDevCentral

No OneTemporary

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

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)

Event Timeline