ServiceFactory.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. *
  87. * @return ServiceInterface
  88. */
  89. public function createService(
  90. $serviceName,
  91. CredentialsInterface $credentials,
  92. TokenStorageInterface $storage,
  93. $scopes = array(),
  94. UriInterface $baseApiUri = null
  95. ) {
  96. if (!$this->httpClient) {
  97. // for backwards compatibility.
  98. $this->httpClient = new StreamClient();
  99. }
  100. foreach ($this->serviceBuilders as $version => $buildMethod) {
  101. $fullyQualifiedServiceName = $this->getFullyQualifiedServiceName($serviceName, $version);
  102. if (class_exists($fullyQualifiedServiceName)) {
  103. return $this->$buildMethod($fullyQualifiedServiceName, $credentials, $storage, $scopes, $baseApiUri);
  104. }
  105. }
  106. return null;
  107. }
  108. /**
  109. * Gets the fully qualified name of the service
  110. *
  111. * @param string $serviceName The name of the service of which to get the fully qualified name
  112. * @param string $type The type of the service to get (either OAuth1 or OAuth2)
  113. *
  114. * @return string The fully qualified name of the service
  115. */
  116. private function getFullyQualifiedServiceName($serviceName, $type)
  117. {
  118. $serviceName = ucfirst($serviceName);
  119. if (isset($this->serviceClassMap[$type][$serviceName])) {
  120. return $this->serviceClassMap[$type][$serviceName];
  121. }
  122. return '\\OAuth\\' . $type . '\\Service\\' . $serviceName;
  123. }
  124. /**
  125. * Builds v2 services
  126. *
  127. * @param string $serviceName The fully qualified service name
  128. * @param CredentialsInterface $credentials
  129. * @param TokenStorageInterface $storage
  130. * @param array|null $scopes Array of scopes for the service
  131. * @param UriInterface|null $baseApiUri
  132. *
  133. * @return ServiceInterface
  134. *
  135. * @throws Exception
  136. */
  137. private function buildV2Service(
  138. $serviceName,
  139. CredentialsInterface $credentials,
  140. TokenStorageInterface $storage,
  141. array $scopes,
  142. UriInterface $baseApiUri = null
  143. ) {
  144. return new $serviceName(
  145. $credentials,
  146. $this->httpClient,
  147. $storage,
  148. $this->resolveScopes($serviceName, $scopes),
  149. $baseApiUri
  150. );
  151. }
  152. /**
  153. * Resolves scopes for v2 services
  154. *
  155. * @param string $serviceName The fully qualified service name
  156. * @param array $scopes List of scopes for the service
  157. *
  158. * @return array List of resolved scopes
  159. */
  160. private function resolveScopes($serviceName, array $scopes)
  161. {
  162. $reflClass = new \ReflectionClass($serviceName);
  163. $constants = $reflClass->getConstants();
  164. $resolvedScopes = array();
  165. foreach ($scopes as $scope) {
  166. $key = strtoupper('SCOPE_' . $scope);
  167. if (array_key_exists($key, $constants)) {
  168. $resolvedScopes[] = $constants[$key];
  169. } else {
  170. $resolvedScopes[] = $scope;
  171. }
  172. }
  173. return $resolvedScopes;
  174. }
  175. /**
  176. * Builds v1 services
  177. *
  178. * @param string $serviceName The fully qualified service name
  179. * @param CredentialsInterface $credentials
  180. * @param TokenStorageInterface $storage
  181. * @param array $scopes
  182. * @param UriInterface $baseApiUri
  183. *
  184. * @return ServiceInterface
  185. *
  186. * @throws Exception
  187. */
  188. private function buildV1Service(
  189. $serviceName,
  190. CredentialsInterface $credentials,
  191. TokenStorageInterface $storage,
  192. $scopes,
  193. UriInterface $baseApiUri = null
  194. ) {
  195. if (!empty($scopes)) {
  196. throw new Exception(
  197. 'Scopes passed to ServiceFactory::createService but an OAuth1 service was requested.'
  198. );
  199. }
  200. return new $serviceName($credentials, $this->httpClient, $storage, new Signature($credentials), $baseApiUri);
  201. }
  202. }