ServiceFactory.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. /**
  3. * OAuth service factory.
  4. *
  5. * PHP version 5.4
  6. *
  7. * @category OAuth
  8. * @author David Desberg <david@daviddesberg.com>
  9. * @author Pieter Hordijk <info@pieterhordijk.com>
  10. * @copyright Copyright (c) 2013 The authors
  11. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  12. */
  13. namespace OAuth;
  14. use OAuth\Common\Service\ServiceInterface;
  15. use OAuth\Common\Consumer\CredentialsInterface;
  16. use OAuth\Common\Storage\TokenStorageInterface;
  17. use OAuth\Common\Http\Client\ClientInterface;
  18. use OAuth\Common\Http\Client\StreamClient;
  19. use OAuth\Common\Http\Uri\UriInterface;
  20. use OAuth\Common\Exception\Exception;
  21. use OAuth\OAuth1\Signature\Signature;
  22. class ServiceFactory
  23. {
  24. /**
  25. *@var ClientInterface
  26. */
  27. protected $httpClient;
  28. /**
  29. * @var array
  30. */
  31. protected $serviceClassMap = array(
  32. 'OAuth1' => array(),
  33. 'OAuth2' => array()
  34. );
  35. /**
  36. * @var array
  37. */
  38. protected $serviceBuilders = array(
  39. 'OAuth2' => 'buildV2Service',
  40. 'OAuth1' => 'buildV1Service',
  41. );
  42. /**
  43. * @param ClientInterface $httpClient
  44. *
  45. * @return ServiceFactory
  46. */
  47. public function setHttpClient(ClientInterface $httpClient)
  48. {
  49. $this->httpClient = $httpClient;
  50. return $this;
  51. }
  52. /**
  53. * Register a custom service to classname mapping.
  54. *
  55. * @param string $serviceName Name of the service
  56. * @param string $className Class to instantiate
  57. *
  58. * @return ServiceFactory
  59. *
  60. * @throws Exception If the class is nonexistent or does not implement a valid ServiceInterface
  61. */
  62. public function registerService($serviceName, $className)
  63. {
  64. if (!class_exists($className)) {
  65. throw new Exception(sprintf('Service class %s does not exist.', $className));
  66. }
  67. $reflClass = new \ReflectionClass($className);
  68. foreach (array('OAuth2', 'OAuth1') as $version) {
  69. if ($reflClass->implementsInterface('OAuth\\' . $version . '\\Service\\ServiceInterface')) {
  70. $this->serviceClassMap[$version][ucfirst($serviceName)] = $className;
  71. return $this;
  72. }
  73. }
  74. throw new Exception(sprintf('Service class %s must implement ServiceInterface.', $className));
  75. }
  76. /**
  77. * Builds and returns oauth services
  78. *
  79. * It will first try to build an OAuth2 service and if none found it will try to build an OAuth1 service
  80. *
  81. * @param string $serviceName Name of service to create
  82. * @param CredentialsInterface $credentials
  83. * @param TokenStorageInterface $storage
  84. * @param array|null $scopes If creating an oauth2 service, array of scopes
  85. * @param UriInterface|null $baseApiUri
  86. * @param string $apiVersion version of the api call
  87. *
  88. * @return ServiceInterface
  89. */
  90. public function createService(
  91. $serviceName,
  92. CredentialsInterface $credentials,
  93. TokenStorageInterface $storage,
  94. $scopes = array(),
  95. UriInterface $baseApiUri = null,
  96. $apiVersion = ""
  97. ) {
  98. if (!$this->httpClient) {
  99. // for backwards compatibility.
  100. $this->httpClient = new StreamClient();
  101. }
  102. foreach ($this->serviceBuilders as $version => $buildMethod) {
  103. $fullyQualifiedServiceName = $this->getFullyQualifiedServiceName($serviceName, $version);
  104. if (class_exists($fullyQualifiedServiceName)) {
  105. return $this->$buildMethod(
  106. $fullyQualifiedServiceName,
  107. $credentials,
  108. $storage,
  109. $scopes,
  110. $baseApiUri,
  111. $apiVersion
  112. );
  113. }
  114. }
  115. return null;
  116. }
  117. /**
  118. * Gets the fully qualified name of the service
  119. *
  120. * @param string $serviceName The name of the service of which to get the fully qualified name
  121. * @param string $type The type of the service to get (either OAuth1 or OAuth2)
  122. *
  123. * @return string The fully qualified name of the service
  124. */
  125. private function getFullyQualifiedServiceName($serviceName, $type)
  126. {
  127. $serviceName = ucfirst($serviceName);
  128. if (isset($this->serviceClassMap[$type][$serviceName])) {
  129. return $this->serviceClassMap[$type][$serviceName];
  130. }
  131. return '\\OAuth\\' . $type . '\\Service\\' . $serviceName;
  132. }
  133. /**
  134. * Builds v2 services
  135. *
  136. * @param string $serviceName The fully qualified service name
  137. * @param CredentialsInterface $credentials
  138. * @param TokenStorageInterface $storage
  139. * @param array|null $scopes Array of scopes for the service
  140. * @param UriInterface|null $baseApiUri
  141. *
  142. * @return ServiceInterface
  143. *
  144. * @throws Exception
  145. */
  146. private function buildV2Service(
  147. $serviceName,
  148. CredentialsInterface $credentials,
  149. TokenStorageInterface $storage,
  150. array $scopes,
  151. UriInterface $baseApiUri = null,
  152. $apiVersion = ""
  153. ) {
  154. return new $serviceName(
  155. $credentials,
  156. $this->httpClient,
  157. $storage,
  158. $this->resolveScopes($serviceName, $scopes),
  159. $baseApiUri,
  160. $apiVersion
  161. );
  162. }
  163. /**
  164. * Resolves scopes for v2 services
  165. *
  166. * @param string $serviceName The fully qualified service name
  167. * @param array $scopes List of scopes for the service
  168. *
  169. * @return array List of resolved scopes
  170. */
  171. private function resolveScopes($serviceName, array $scopes)
  172. {
  173. $reflClass = new \ReflectionClass($serviceName);
  174. $constants = $reflClass->getConstants();
  175. $resolvedScopes = array();
  176. foreach ($scopes as $scope) {
  177. $key = strtoupper('SCOPE_' . $scope);
  178. if (array_key_exists($key, $constants)) {
  179. $resolvedScopes[] = $constants[$key];
  180. } else {
  181. $resolvedScopes[] = $scope;
  182. }
  183. }
  184. return $resolvedScopes;
  185. }
  186. /**
  187. * Builds v1 services
  188. *
  189. * @param string $serviceName The fully qualified service name
  190. * @param CredentialsInterface $credentials
  191. * @param TokenStorageInterface $storage
  192. * @param array $scopes
  193. * @param UriInterface $baseApiUri
  194. *
  195. * @return ServiceInterface
  196. *
  197. * @throws Exception
  198. */
  199. private function buildV1Service(
  200. $serviceName,
  201. CredentialsInterface $credentials,
  202. TokenStorageInterface $storage,
  203. $scopes,
  204. UriInterface $baseApiUri = null
  205. ) {
  206. if (!empty($scopes)) {
  207. throw new Exception(
  208. 'Scopes passed to ServiceFactory::createService but an OAuth1 service was requested.'
  209. );
  210. }
  211. return new $serviceName($credentials, $this->httpClient, $storage, new Signature($credentials), $baseApiUri);
  212. }
  213. }