Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3920347
D317.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
21 KB
Referenced Files
None
Subscribers
None
D317.diff
View Options
diff --git a/app/Facades/PhabricatorAPI.php b/app/Facades/PhabricatorAPI.php
new file mode 100644
--- /dev/null
+++ b/app/Facades/PhabricatorAPI.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Nasqueron\Notifications\Facades;
+
+use Illuminate\Support\Facades\Facade;
+
+/**
+ * @see \Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory
+ */
+class PhabricatorAPI extends Facade {
+
+ /**
+ * Gets the registered name of the component.
+ *
+ * @return string
+ */
+ protected static function getFacadeAccessor() {
+ return 'phabricator-api';
+ }
+
+}
diff --git a/app/Facades/ProjectsMap.php b/app/Facades/ProjectsMap.php
new file mode 100644
--- /dev/null
+++ b/app/Facades/ProjectsMap.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Nasqueron\Notifications\Facades;
+
+use Illuminate\Support\Facades\Facade;
+
+/**
+ * @see \Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory
+ */
+class ProjectsMap extends Facade {
+
+ /**
+ * Gets the registered name of the component.
+ *
+ * @return string
+ */
+ protected static function getFacadeAccessor() {
+ return 'phabricator-projectsmap';
+ }
+
+}
diff --git a/app/Phabricator/PhabricatorAPIFactory.php b/app/Phabricator/PhabricatorAPIFactory.php
new file mode 100644
--- /dev/null
+++ b/app/Phabricator/PhabricatorAPIFactory.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Nasqueron\Notifications\Phabricator;
+
+class PhabricatorAPIFactory {
+
+ /**
+ * Gets an instance of the Phabricator API client class
+ *
+ * @param string $instance The Phabricator instance
+ * @return Nasqueron\Notifications\Phabricator\PhabricatorAPI
+ */
+ public function get ($instance) {
+ return PhabricatorAPI::forInstance($instance);
+ }
+
+ /**
+ * Gets an instance of the Phabricator API client class for a project
+ *
+ * @param string $project The Phabricator project name
+ * @return Nasqueron\Notifications\Phabricator\PhabricatorAPI
+ */
+ public function getForProject ($project) {
+ return PhabricatorAPI::forProject($project);
+ }
+}
diff --git a/app/Phabricator/ProjectsMap.php b/app/Phabricator/ProjectsMap.php
--- a/app/Phabricator/ProjectsMap.php
+++ b/app/Phabricator/ProjectsMap.php
@@ -11,29 +11,29 @@
///
/**
- * The maximum number of projects to fetch
- */
+ * 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[]
- */
+ * 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
- */
+ * The Phabricator instance for this projects map
+ *
+ * @var string
+ */
private $instance;
/**
- * The source of the map
- *
- * @var string
- */
+ * The source of the map
+ *
+ * @var string
+ */
private $source = 'unloaded';
///
@@ -41,10 +41,10 @@
///
/**
- * Initializes a new instance of ProjectsMap
- *
- * @param string $instance The Phabricator root URL without trailing slash
- */
+ * Initializes a new instance of ProjectsMap
+ *
+ * @param string $instance The Phabricator root URL without trailing slash
+ */
public function __construct ($instance) {
$this->instance = $instance;
}
@@ -54,10 +54,10 @@
///
/**
- * Gets iterator
- *
- * @return Traversable
- */
+ * Gets iterator
+ *
+ * @return Traversable
+ */
public function getIterator ( ) {
return new \ArrayIterator($this->map);
}
@@ -67,39 +67,39 @@
///
/**
- * Determines whether an offset exists
- *
- * @param mixed $offset The offset
- */
+ * 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
- */
+ * 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
- */
+ * 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
- */
+ * Unset an offset
+ *
+ * @param mixed $offset The offset
+ */
public function offsetUnset ($offset) {
unset($this->map[$offset]);
}
@@ -109,33 +109,33 @@
///
/**
- * 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
- */
+ * 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);
+ $instance = new self($phabricatorURL);
- if ($instance->isCached()) {
- $instance->loadFromCache();
- } else {
- $instance->fetchFromAPI();
- }
+ if ($instance->isCached()) {
+ $instance->loadFromCache();
+ } else {
+ $instance->fetchFromAPI();
+ }
- return $instance;
+ return $instance;
}
/**
- * 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
- */
+ * 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;
+ $instance = new self($phabricatorURL);
+ $instance->fetchFromAPI();
+ return $instance;
}
///
@@ -143,27 +143,27 @@
///
/**
- * Fetches the projects' map from the Phabricator API
- */
+ * Fetches the projects' map from the Phabricator API
+ */
private function fetchFromAPI () {
- $reply = PhabricatorAPI::forInstance($this->instance)->call(
- 'project.query',
- [ 'limit' => self::LIMIT ]
+ $reply = \PhabricatorAPI::get($this->instance)->call(
+ 'project.query',
+ [ 'limit' => self::LIMIT ]
);
- if (!$reply) {
- throw new \Exception("Empty reply calling project.query at $this->instance API.");
- }
+ 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.");
- }
+ 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);
- }
+ foreach ($reply->data as $phid => $projectInfo) {
+ $this->offsetSet($phid, $projectInfo->name);
+ }
- $this->source = 'api';
+ $this->source = 'api';
}
///
@@ -171,35 +171,35 @@
///
/**
- * Gets cache key
- *
- * @return string The cache key for the current projects map
- */
+ * 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);
}
/**
- * Determines if the instance is cached
- *
- * @return bool true if cached; otherwise, false.
- */
+ * Determines if the instance is cached
+ *
+ * @return bool true if cached; otherwise, false.
+ */
public function isCached () {
return Cache::has($this->getCacheKey());
}
/**
- * Saves data to cache
- */
+ * Saves data to cache
+ */
public function saveToCache () {
Cache::forever($this->getCacheKey(), $this->map);
}
/**
- * Loads data from cache
- *
- * Populates 'map' and 'source' properties
- */
+ * Loads data from cache
+ *
+ * Populates 'map' and 'source' properties
+ */
public function loadFromCache () {
$this->map = Cache::get($this->getCacheKey());
$this->source = 'cache';
@@ -210,11 +210,11 @@
///
/**
- * Gets project name, refreshing the cache if needed
- *
- * @param string $projectPHID the PHID of the project to query the name
- * @return string
- */
+ * 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);
@@ -229,10 +229,10 @@
}
/**
- * Returns the projects map as an array, each row ['PHID', 'project name']
- *
- * @return array
- */
+ * Returns the projects map as an array, each row ['PHID', 'project name']
+ *
+ * @return array
+ */
public function toArray () {
$array = [];
foreach ($this->map as $phid => $projectName) {
diff --git a/app/Phabricator/ProjectsMapFactory.php b/app/Phabricator/ProjectsMapFactory.php
new file mode 100644
--- /dev/null
+++ b/app/Phabricator/ProjectsMapFactory.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Nasqueron\Notifications\Phabricator;
+
+class ProjectsMapFactory {
+
+ /**
+ * Loads projects map from cache or fetches it from API if not cached
+ *
+ * @param string $instance The Phabricator instance
+ * @return Nasqueron\Notifications\Phabricator\ProjectsMap
+ */
+ public function load ($instance) {
+ return ProjectsMap::load($instance);
+ }
+
+ /**
+ * Fetches projects map from API
+ *
+ * @param string $instance The Phabricator instance
+ * @return Nasqueron\Notifications\Phabricator\ProjectsMap
+ */
+ public function fetch ($instance) {
+ return ProjectsMap::fetch($instance);
+ }
+
+}
diff --git a/app/Providers/PhabricatorAPIServiceProvider.php b/app/Providers/PhabricatorAPIServiceProvider.php
new file mode 100644
--- /dev/null
+++ b/app/Providers/PhabricatorAPIServiceProvider.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Nasqueron\Notifications\Providers;
+
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Support\ServiceProvider;
+
+use Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory;
+
+class PhabricatorAPIServiceProvider extends ServiceProvider
+{
+ /**
+ * Bootstraps the application services.
+ *
+ * @return void
+ */
+ public function boot() {
+ }
+
+ /**
+ * Registers the application services.
+ *
+ * @return void
+ */
+ public function register() {
+ $this->app->singleton('phabricator-api', function () {
+ return new PhabricatorAPIFactory;
+ });
+ }
+}
diff --git a/app/Providers/PhabricatorProjectsMapServiceProvider.php b/app/Providers/PhabricatorProjectsMapServiceProvider.php
new file mode 100644
--- /dev/null
+++ b/app/Providers/PhabricatorProjectsMapServiceProvider.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Nasqueron\Notifications\Providers;
+
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Support\ServiceProvider;
+
+use Nasqueron\Notifications\Phabricator\ProjectsMapFactory;
+
+class PhabricatorProjectsMapServiceProvider extends ServiceProvider
+{
+ /**
+ * Bootstraps the application services.
+ *
+ * @return void
+ */
+ public function boot() {
+ }
+
+ /**
+ * Registers the application services.
+ *
+ * @return void
+ */
+ public function register() {
+ $this->app->singleton('phabricator-projectsmap', function () {
+ return new ProjectsMapFactory;
+ });
+ }
+}
diff --git a/config/app.php b/config/app.php
--- a/config/app.php
+++ b/config/app.php
@@ -172,6 +172,8 @@
Nasqueron\Notifications\Providers\AppServiceProvider::class,
Nasqueron\Notifications\Providers\BrokerServiceProvider::class,
Nasqueron\Notifications\Providers\EventServiceProvider::class,
+ Nasqueron\Notifications\Providers\PhabricatorAPIServiceProvider::class,
+ Nasqueron\Notifications\Providers\PhabricatorProjectsMapServiceProvider::class,
Nasqueron\Notifications\Providers\ReportServiceProvider::class,
Nasqueron\Notifications\Providers\RouteServiceProvider::class,
Nasqueron\Notifications\Providers\SentryServiceProvider::class,
@@ -249,6 +251,8 @@
* App aliases...
*/
'Broker' => Nasqueron\Notifications\Facades\Broker::class,
+ 'PhabricatorAPI' => Nasqueron\Notifications\Facades\PhabricatorAPI::class,
+ 'ProjectsMap' => Nasqueron\Notifications\Facades\ProjectsMap::class,
'Raven' => Nasqueron\Notifications\Facades\Raven::class,
'Report' => Nasqueron\Notifications\Facades\Report::class,
'Services' => Nasqueron\Notifications\Facades\Services::class,
diff --git a/tests/Facades/PhabricatorAPITest.php b/tests/Facades/PhabricatorAPITest.php
new file mode 100644
--- /dev/null
+++ b/tests/Facades/PhabricatorAPITest.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Facades;
+
+use Nasqueron\Notifications\Facades\PhabricatorAPI;
+use Nasqueron\Notifications\Tests\TestCase;
+
+class PhabricatorAPITest extends TestCase {
+
+ public function testIfFacadeAccessorCouldBeResolvedInAppContainer () {
+ $this->assertInstanceOf(
+ 'Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory',
+ PhabricatorAPI::getFacadeRoot()
+ );
+ }
+}
diff --git a/tests/Facades/ProjectsMapTest.php b/tests/Facades/ProjectsMapTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Facades/ProjectsMapTest.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Facades;
+
+use Nasqueron\Notifications\Facades\ProjectsMap;
+use Nasqueron\Notifications\Tests\TestCase;
+
+class ProjectsMapTest extends TestCase {
+
+ public function testIfFacadeAccessorCouldBeResolvedInAppContainer () {
+ $this->assertInstanceOf(
+ 'Nasqueron\Notifications\Phabricator\ProjectsMapFactory',
+ ProjectsMap::getFacadeRoot()
+ );
+ }
+}
diff --git a/tests/Phabricator/PhabricatorAPIFactoryTest.php b/tests/Phabricator/PhabricatorAPIFactoryTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Phabricator/PhabricatorAPIFactoryTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Phabricator;
+
+use Nasqueron\Notifications\Tests\TestCase;
+
+class PhabricatorAPIFactoryTest extends TestCase {
+
+ /**
+ * @var \Nasqueron\Notifications\Phabricator\ProjectsMapFactory
+ */
+ private $factory;
+
+ public function setUp () {
+ parent::setUp();
+ $this->factory = $this->app->make('phabricator-api');
+ }
+
+ public function testGetAPI () {
+ $this->assertInstanceOf(
+ '\Nasqueron\Notifications\Phabricator\PhabricatorAPI',
+ $this->factory->get("https://phabricator.acme.tld")
+ );
+ }
+
+ public function testGetAPIForProject () {
+ $this->assertInstanceOf(
+ '\Nasqueron\Notifications\Phabricator\PhabricatorAPI',
+ $this->factory->getForProject("Acme")
+ );
+ }
+}
diff --git a/tests/Phabricator/ProjectsMapFactoryTest.php b/tests/Phabricator/ProjectsMapFactoryTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Phabricator/ProjectsMapFactoryTest.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Phabricator;
+
+use Nasqueron\Notifications\Tests\TestCase;
+
+class ProjectsMapFactoryTest extends TestCase {
+
+ /**
+ * @var \Nasqueron\Notifications\Phabricator\ProjectsMapFactory
+ */
+ private $factory;
+
+ public function setUp () {
+ parent::setUp();
+ $this->factory = $this->app->make('phabricator-projectsmap');
+
+ $mock = $this->mockPhabricatorAPIForProjectsMap();
+ }
+
+ public function testLoadProjectsMap () {
+ $this->assertInstanceOf(
+ '\Nasqueron\Notifications\Phabricator\ProjectsMap',
+ $this->factory->load("https://phabricator.acme.tld")
+ );
+ }
+
+ public function testFetchProjectsMap () {
+ $this->assertInstanceOf(
+ '\Nasqueron\Notifications\Phabricator\ProjectsMap',
+ $this->factory->fetch("https://phabricator.acme.tld")
+ );
+ }
+
+}
diff --git a/tests/Providers/PhabricatorAPIServiceProviderTest.php b/tests/Providers/PhabricatorAPIServiceProviderTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Providers/PhabricatorAPIServiceProviderTest.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Providers;
+
+class PhabricatorAPIServiceProviderTest extends TestCase {
+
+ public function testType () {
+ $this->assertServiceInstanceOf(
+ 'Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory',
+ 'phabricator-api'
+ );
+ }
+
+}
diff --git a/tests/Providers/PhabricatorProjectsMapServiceProviderTest.php b/tests/Providers/PhabricatorProjectsMapServiceProviderTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Providers/PhabricatorProjectsMapServiceProviderTest.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace Nasqueron\Notifications\Tests\Providers;
+
+class PhabricatorProjectsMapServiceProviderTest extends TestCase {
+
+ public function testType () {
+ $this->assertServiceInstanceOf(
+ 'Nasqueron\Notifications\Phabricator\ProjectsMapFactory',
+ 'phabricator-projectsmap'
+ );
+ }
+
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -70,6 +70,34 @@
$this->app->instance('broker', $mock);
}
+ /**
+ * Mocks the Phabricator API
+ *
+ * @return Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory The mock
+ */
+ protected function mockPhabricatorAPI () {
+ // Inject into our container a mock of PhabricatorAPI
+ $mock = Mockery::mock('Nasqueron\Notifications\Phabricator\PhabricatorAPIFactory');
+ $this->app->instance('phabricator-api', $mock);
+
+ return $mock;
+ }
+
+ private function mockPhabricatorAPIProjectsQueryReply () {
+ $json = file_get_contents('tests/data/PhabricatorProjetsQueryReply.json');
+ return json_decode($json);
+ }
+
+ /**
+ * Mocks the Phabricator API
+ */
+ protected function mockPhabricatorAPIForProjectsMap () {
+ $mock = $this->mockPhabricatorAPI();
+
+ $reply = $this->mockPhabricatorAPIProjectsQueryReply();
+ $mock->shouldReceive('get->call')->andReturn($reply);
+ }
+
///
/// Helpers to post data to gates
///
diff --git a/tests/data/PhabricatorProjetsQueryReply.json b/tests/data/PhabricatorProjetsQueryReply.json
new file mode 100644
--- /dev/null
+++ b/tests/data/PhabricatorProjetsQueryReply.json
@@ -0,0 +1,61 @@
+{
+ "data": {
+ "PHID-PROJ-6dg6ogx5pjmk24ur4tp4": {
+ "id": "60",
+ "phid": "PHID-PROJ-6dg6ogx5pjmk24ur4tp4",
+ "name": "Accounts",
+ "profileImagePHID": "PHID-FILE-fgoutnn6wzccr6w2nldv",
+ "icon": "tag",
+ "color": "orange",
+ "members": [
+ "PHID-USER-fnetlprx7zdotfm2hdrz"
+ ],
+ "slugs": [
+ "accounts"
+ ],
+ "dateCreated": "1453142137",
+ "dateModified": "1453142157"
+ },
+ "PHID-PROJ-cztcgpvqr6smnnekotq7": {
+ "id": "17",
+ "phid": "PHID-PROJ-cztcgpvqr6smnnekotq7",
+ "name": "Agora",
+ "profileImagePHID": "PHID-FILE-2lbihkjdnretjk52wmoi",
+ "icon": "folder",
+ "color": "blue",
+ "members": [
+ "PHID-USER-fnetlprx7zdotfm2hdrz"
+ ],
+ "slugs": [
+ "agora",
+ "wiki"
+ ],
+ "dateCreated": "1417065185",
+ "dateModified": "1417076656"
+ },
+ "PHID-PROJ-3iew3cqf3htpazfyzb5a": {
+ "id": "29",
+ "phid": "PHID-PROJ-3iew3cqf3htpazfyzb5a",
+ "name": "architecture",
+ "profileImagePHID": "PHID-FILE-bljt7kpva2cwkx6omh2j",
+ "icon": "tag",
+ "color": "orange",
+ "members": [
+ "PHID-USER-fnetlprx7zdotfm2hdrz"
+ ],
+ "slugs": [
+ "architecture",
+ "architect",
+ "archi"
+ ],
+ "dateCreated": "1427725535",
+ "dateModified": "1427725949"
+ }
+ },
+ "slugMap": [],
+ "cursor": {
+ "limit": "3",
+ "after": "29",
+ "before": null
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 14:30 (19 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2309583
Default Alt Text
D317.diff (21 KB)
Attached To
Mode
D317: Service providers for PhabricatorAPI and ProjectsMap
Attached
Detach File
Event Timeline
Log In to Comment