PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/backwpup/vendor/OpenCloud/Common/Resource/PersistentResource.php

https://gitlab.com/pankajmohale/chef2go
PHP | 391 lines | 205 code | 58 blank | 128 comment | 29 complexity | b73fe3bdb707e70bc6b5a5b0ebb886a3 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2012-2014 Rackspace US, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace OpenCloud\Common\Resource;
  18. use Guzzle\Http\Url;
  19. use OpenCloud\Common\Constants\State;
  20. use OpenCloud\Common\Exceptions\CreateError;
  21. use OpenCloud\Common\Exceptions\DeleteError;
  22. use OpenCloud\Common\Exceptions\IdRequiredError;
  23. use OpenCloud\Common\Exceptions\NameError;
  24. use OpenCloud\Common\Exceptions\UnsupportedExtensionError;
  25. use OpenCloud\Common\Exceptions\UpdateError;
  26. abstract class PersistentResource extends BaseResource
  27. {
  28. /**
  29. * Create a new resource
  30. *
  31. * @param array $params
  32. * @return \Guzzle\Http\Message\Response
  33. */
  34. public function create($params = array())
  35. {
  36. // set parameters
  37. if (!empty($params)) {
  38. $this->populate($params, false);
  39. }
  40. // construct the JSON
  41. $json = json_encode($this->createJson());
  42. $this->checkJsonError();
  43. $createUrl = $this->createUrl();
  44. $response = $this->getClient()->post($createUrl, self::getJsonHeader(), $json)->send();
  45. // We have to try to parse the response body first because it should have precedence over a Location refresh.
  46. // I'd like to reverse the order, but Nova instances return ephemeral properties on creation which are not
  47. // available when you follow the Location link...
  48. if (null !== ($decoded = $this->parseResponse($response))) {
  49. $this->populate($decoded);
  50. } elseif ($location = $response->getHeader('Location')) {
  51. $this->refreshFromLocationUrl($location);
  52. }
  53. return $response;
  54. }
  55. /**
  56. * Update a resource
  57. *
  58. * @param array $params
  59. * @return \Guzzle\Http\Message\Response
  60. */
  61. public function update($params = array())
  62. {
  63. // set parameters
  64. if (!empty($params)) {
  65. $this->populate($params);
  66. }
  67. // construct the JSON
  68. $json = json_encode($this->updateJson($params));
  69. $this->checkJsonError();
  70. // send the request
  71. return $this->getClient()->put($this->getUrl(), self::getJsonHeader(), $json)->send();
  72. }
  73. /**
  74. * Delete this resource
  75. *
  76. * @return \Guzzle\Http\Message\Response
  77. */
  78. public function delete()
  79. {
  80. return $this->getClient()->delete($this->getUrl())->send();
  81. }
  82. /**
  83. * Refresh the state of a resource
  84. *
  85. * @param null $id
  86. * @param null $url
  87. * @return \Guzzle\Http\Message\Response
  88. * @throws IdRequiredError
  89. */
  90. public function refresh($id = null, $url = null)
  91. {
  92. $primaryKey = $this->primaryKeyField();
  93. $primaryKeyVal = $this->getProperty($primaryKey);
  94. if (!$url) {
  95. if (!$id = $id ?: $primaryKeyVal) {
  96. $message = sprintf("This resource cannot be refreshed because it has no %s", $primaryKey);
  97. throw new IdRequiredError($message);
  98. }
  99. if ($primaryKeyVal != $id) {
  100. $this->setProperty($primaryKey, $id);
  101. }
  102. $url = $this->getUrl();
  103. }
  104. // reset status, if available
  105. if ($this->getProperty('status')) {
  106. $this->setProperty('status', null);
  107. }
  108. $response = $this->getClient()->get($url)->send();
  109. if (null !== ($decoded = $this->parseResponse($response))) {
  110. $this->populate($decoded);
  111. }
  112. return $response;
  113. }
  114. /**
  115. * Causes resource to refresh based on parent's URL
  116. */
  117. protected function refreshFromParent()
  118. {
  119. $url = clone $this->getParent()->getUrl();
  120. $url->addPath($this->resourceName());
  121. $response = $this->getClient()->get($url)->send();
  122. if (null !== ($decoded = $this->parseResponse($response))) {
  123. $this->populate($decoded);
  124. }
  125. }
  126. /**
  127. * Given a `location` URL, refresh this resource
  128. *
  129. * @param $url
  130. */
  131. public function refreshFromLocationUrl($url)
  132. {
  133. $fullUrl = Url::factory($url);
  134. $response = $this->getClient()->get($fullUrl)->send();
  135. if (null !== ($decoded = $this->parseResponse($response))) {
  136. $this->populate($decoded);
  137. }
  138. }
  139. /**
  140. * A method to repeatedly poll the API resource, waiting for an eventual state change
  141. *
  142. * @param null $state The expected state of the resource
  143. * @param null $timeout The maximum timeout to wait
  144. * @param null $callback The callback to use to check the state
  145. * @param null $interval How long between each refresh request
  146. */
  147. public function waitFor($state = null, $timeout = null, $callback = null, $interval = null)
  148. {
  149. $state = $state ?: State::ACTIVE;
  150. $timeout = $timeout ?: State::DEFAULT_TIMEOUT;
  151. $interval = $interval ?: State::DEFAULT_INTERVAL;
  152. // save stats
  153. $startTime = time();
  154. $states = array('ERROR', $state);
  155. while (true) {
  156. $this->refresh($this->getProperty($this->primaryKeyField()));
  157. if ($callback) {
  158. call_user_func($callback, $this);
  159. }
  160. if (in_array($this->status(), $states) || (time() - $startTime) > $timeout) {
  161. return;
  162. }
  163. sleep($interval);
  164. }
  165. }
  166. /**
  167. * Provides JSON for create request body
  168. *
  169. * @return object
  170. * @throws \RuntimeException
  171. */
  172. protected function createJson()
  173. {
  174. if (!isset($this->createKeys)) {
  175. throw new \RuntimeException(sprintf(
  176. 'This resource object [%s] must have a visible createKeys array',
  177. get_class($this)
  178. ));
  179. }
  180. $element = (object) array();
  181. foreach ($this->createKeys as $key) {
  182. if (null !== ($property = $this->getProperty($key))) {
  183. $element->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($property);
  184. }
  185. }
  186. if (isset($this->metadata) && count($this->metadata)) {
  187. $element->metadata = (object) $this->metadata->toArray();
  188. }
  189. return (object) array($this->jsonName() => (object) $element);
  190. }
  191. /**
  192. * Returns the alias configured for the given key. If no alias exists
  193. * it returns the original key.
  194. *
  195. * @param string $key
  196. * @return string
  197. */
  198. protected function getAlias($key)
  199. {
  200. if (false !== ($alias = array_search($key, $this->aliases))) {
  201. return $alias;
  202. }
  203. return $key;
  204. }
  205. /**
  206. * Returns the given property value's alias, if configured; Else, the
  207. * unchanged property value is returned. If the given property value
  208. * is an array or an instance of \stdClass, it is aliases recursively.
  209. *
  210. * @param mixed $propertyValue Array or \stdClass instance to alias
  211. * @return mixed Property value, aliased recursively
  212. */
  213. protected function recursivelyAliasPropertyValue($propertyValue)
  214. {
  215. if (is_array($propertyValue)) {
  216. foreach ($propertyValue as $key => $subValue) {
  217. $aliasedSubValue = $this->recursivelyAliasPropertyValue($subValue);
  218. if (is_numeric($key)) {
  219. $propertyValue[$key] = $aliasedSubValue;
  220. } else {
  221. unset($propertyValue[$key]);
  222. $propertyValue[$this->getAlias($key)] = $aliasedSubValue;
  223. }
  224. }
  225. } elseif (is_object($propertyValue) && ($propertyValue instanceof \stdClass)) {
  226. foreach ($propertyValue as $key => $subValue) {
  227. unset($propertyValue->$key);
  228. $propertyValue->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($subValue);
  229. }
  230. }
  231. return $propertyValue;
  232. }
  233. /**
  234. * Provides JSON for update request body
  235. */
  236. protected function updateJson($params = array())
  237. {
  238. if (!isset($this->updateKeys)) {
  239. throw new \RuntimeException(sprintf(
  240. 'This resource object [%s] must have a visible updateKeys array',
  241. get_class($this)
  242. ));
  243. }
  244. $element = (object) array();
  245. foreach ($this->updateKeys as $key) {
  246. if (null !== ($property = $this->getProperty($key))) {
  247. $element->{$this->getAlias($key)} = $this->recursivelyAliasPropertyValue($property);
  248. }
  249. }
  250. return (object) array($this->jsonName() => (object) $element);
  251. }
  252. /**
  253. * @throws CreateError
  254. */
  255. protected function noCreate()
  256. {
  257. throw new CreateError('This resource does not support the create operation');
  258. }
  259. /**
  260. * @throws DeleteError
  261. */
  262. protected function noDelete()
  263. {
  264. throw new DeleteError('This resource does not support the delete operation');
  265. }
  266. /**
  267. * @throws UpdateError
  268. */
  269. protected function noUpdate()
  270. {
  271. throw new UpdateError('his resource does not support the update operation');
  272. }
  273. /**
  274. * Check whether an extension is valid
  275. *
  276. * @param mixed $alias The extension name
  277. * @return bool
  278. * @throws UnsupportedExtensionError
  279. */
  280. public function checkExtension($alias)
  281. {
  282. if (!in_array($alias, $this->getService()->namespaces())) {
  283. throw new UnsupportedExtensionError(sprintf("%s extension is not installed", $alias));
  284. }
  285. return true;
  286. }
  287. /******** DEPRECATED METHODS ********/
  288. /**
  289. * @deprecated
  290. * @return string
  291. * @throws NameError
  292. */
  293. public function name()
  294. {
  295. if (null !== ($name = $this->getProperty('name'))) {
  296. return $name;
  297. } else {
  298. throw new NameError('Name attribute does not exist for this resource');
  299. }
  300. }
  301. /**
  302. * @deprecated
  303. * @return mixed
  304. */
  305. public function id()
  306. {
  307. return $this->id;
  308. }
  309. /**
  310. * @deprecated
  311. * @return string
  312. */
  313. public function status()
  314. {
  315. return (isset($this->status)) ? $this->status : 'N/A';
  316. }
  317. /**
  318. * @deprecated
  319. * @return mixed
  320. */
  321. public function region()
  322. {
  323. return $this->getService()->region();
  324. }
  325. /**
  326. * @deprecated
  327. * @return \Guzzle\Http\Url
  328. */
  329. public function createUrl()
  330. {
  331. return $this->getParent()->getUrl($this->resourceName());
  332. }
  333. }