PageRenderTime 63ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Zend/Cloud/DocumentService/Adapter/SimpleDb.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 468 lines | 246 code | 47 blank | 175 comment | 32 complexity | 4b13a62bd86ab6a181d7fef032c89222 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  1. <?php
  2. /**
  3. * LICENSE
  4. *
  5. * This source file is subject to the new BSD license that is bundled
  6. * with this package in the file LICENSE.txt.
  7. * It is also available through the world-wide-web at this URL:
  8. * http://framework.zend.com/license/new-bsd
  9. * If you did not receive a copy of the license and are unable to
  10. * obtain it through the world-wide-web, please send an email
  11. * to license@zend.com so we can send you a copy immediately.
  12. *
  13. * @category Zend
  14. * @package Zend_Cloud
  15. * @subpackage DocumentService
  16. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  17. * @license http://framework.zend.com/license/new-bsd New BSD License
  18. */
  19. #require_once 'Zend/Cloud/DocumentService/Adapter/AbstractAdapter.php';
  20. #require_once 'Zend/Cloud/DocumentService/Adapter/SimpleDb/Query.php';
  21. #require_once 'Zend/Cloud/DocumentService/Exception.php';
  22. #require_once 'Zend/Service/Amazon/SimpleDb.php';
  23. #require_once 'Zend/Service/Amazon/SimpleDb/Attribute.php';
  24. /**
  25. * SimpleDB adapter for document service.
  26. *
  27. * @category Zend
  28. * @package Zend_Cloud
  29. * @subpackage DocumentService
  30. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  31. * @license http://framework.zend.com/license/new-bsd New BSD License
  32. */
  33. class Zend_Cloud_DocumentService_Adapter_SimpleDb
  34. extends Zend_Cloud_DocumentService_Adapter_AbstractAdapter
  35. {
  36. /*
  37. * Options array keys for the SimpleDB adapter.
  38. */
  39. const AWS_ACCESS_KEY = 'aws_accesskey';
  40. const AWS_SECRET_KEY = 'aws_secretkey';
  41. const ITEM_NAME = 'ItemName';
  42. const MERGE_OPTION = "merge";
  43. const RETURN_DOCUMENTS = "return_documents";
  44. const DEFAULT_QUERY_CLASS = 'Zend_Cloud_DocumentService_Adapter_SimpleDb_Query';
  45. /**
  46. * SQS service instance.
  47. * @var Zend_Service_Amazon_SimpleDb
  48. */
  49. protected $_simpleDb;
  50. /**
  51. * Class to utilize for new query objects
  52. * @var string
  53. */
  54. protected $_queryClass = 'Zend_Cloud_DocumentService_Adapter_SimpleDb_Query';
  55. /**
  56. * Constructor
  57. *
  58. * @param array|Zend_Config $options
  59. * @return void
  60. */
  61. public function __construct($options = array())
  62. {
  63. if ($options instanceof Zend_Config) {
  64. $options = $options->toArray();
  65. }
  66. if (!is_array($options)) {
  67. throw new Zend_Cloud_DocumentService_Exception('Invalid options provided to constructor');
  68. }
  69. $this->_simpleDb = new Zend_Service_Amazon_SimpleDb(
  70. $options[self::AWS_ACCESS_KEY], $options[self::AWS_SECRET_KEY]
  71. );
  72. if (isset($options[self::HTTP_ADAPTER])) {
  73. $this->_sqs->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]);
  74. }
  75. if (isset($options[self::DOCUMENT_CLASS])) {
  76. $this->setDocumentClass($options[self::DOCUMENT_CLASS]);
  77. }
  78. if (isset($options[self::DOCUMENTSET_CLASS])) {
  79. $this->setDocumentSetClass($options[self::DOCUMENTSET_CLASS]);
  80. }
  81. if (isset($options[self::QUERY_CLASS])) {
  82. $this->setQueryClass($options[self::QUERY_CLASS]);
  83. }
  84. }
  85. /**
  86. * Create collection.
  87. *
  88. * @param string $name
  89. * @param array $options
  90. * @return void
  91. */
  92. public function createCollection($name, $options = null)
  93. {
  94. try {
  95. $this->_simpleDb->createDomain($name);
  96. } catch(Zend_Service_Amazon_Exception $e) {
  97. throw new Zend_Cloud_DocumentService_Exception('Error on domain creation: '.$e->getMessage(), $e->getCode(), $e);
  98. }
  99. }
  100. /**
  101. * Delete collection.
  102. *
  103. * @param string $name
  104. * @param array $options
  105. * @return void
  106. */
  107. public function deleteCollection($name, $options = null)
  108. {
  109. try {
  110. $this->_simpleDb->deleteDomain($name);
  111. } catch(Zend_Service_Amazon_Exception $e) {
  112. throw new Zend_Cloud_DocumentService_Exception('Error on collection deletion: '.$e->getMessage(), $e->getCode(), $e);
  113. }
  114. }
  115. /**
  116. * List collections.
  117. *
  118. * @param array $options
  119. * @return array
  120. */
  121. public function listCollections($options = null)
  122. {
  123. try {
  124. // TODO package this in Pages
  125. $domains = $this->_simpleDb->listDomains()->getData();
  126. } catch(Zend_Service_Amazon_Exception $e) {
  127. throw new Zend_Cloud_DocumentService_Exception('Error on collection deletion: '.$e->getMessage(), $e->getCode(), $e);
  128. }
  129. return $domains;
  130. }
  131. /**
  132. * List documents
  133. *
  134. * Returns a key/value array of document names to document objects.
  135. *
  136. * @param string $collectionName Name of collection for which to list documents
  137. * @param array|null $options
  138. * @return Zend_Cloud_DocumentService_DocumentSet
  139. */
  140. public function listDocuments($collectionName, array $options = null)
  141. {
  142. $query = $this->select('*')->from($collectionName);
  143. $items = $this->query($collectionName, $query, $options);
  144. return $items;
  145. }
  146. /**
  147. * Insert document
  148. *
  149. * @param string $collectionName Collection into which to insert document
  150. * @param array|Zend_Cloud_DocumentService_Document $document
  151. * @param array $options
  152. * @return void
  153. */
  154. public function insertDocument($collectionName, $document, $options = null)
  155. {
  156. if (is_array($document)) {
  157. $document = $this->_getDocumentFromArray($document);
  158. }
  159. if (!$document instanceof Zend_Cloud_DocumentService_Document) {
  160. throw new Zend_Cloud_DocumentService_Exception('Invalid document supplied');
  161. }
  162. try {
  163. $this->_simpleDb->putAttributes(
  164. $collectionName,
  165. $document->getID(),
  166. $this->_makeAttributes($document->getID(), $document->getFields())
  167. );
  168. } catch(Zend_Service_Amazon_Exception $e) {
  169. throw new Zend_Cloud_DocumentService_Exception('Error on document insertion: '.$e->getMessage(), $e->getCode(), $e);
  170. }
  171. }
  172. /**
  173. * Replace an existing document with a new version
  174. *
  175. * @param string $collectionName
  176. * @param array|Zend_Cloud_DocumentService_Document $document
  177. * @param array $options
  178. * @return void
  179. */
  180. public function replaceDocument($collectionName, $document, $options = null)
  181. {
  182. if (is_array($document)) {
  183. $document = $this->_getDocumentFromArray($document);
  184. }
  185. if (!$document instanceof Zend_Cloud_DocumentService_Document) {
  186. throw new Zend_Cloud_DocumentService_Exception('Invalid document supplied');
  187. }
  188. // Delete document first, then insert. PutAttributes always keeps any
  189. // fields not referenced in the payload, but present in the document
  190. $documentId = $document->getId();
  191. $fields = $document->getFields();
  192. $docClass = get_class($document);
  193. $this->deleteDocument($collectionName, $document, $options);
  194. $document = new $docClass($fields, $documentId);
  195. $this->insertDocument($collectionName, $document);
  196. }
  197. /**
  198. * Update document. The new document replaces the existing document.
  199. *
  200. * Option 'merge' specifies to add all attributes (if true) or
  201. * specific attributes ("attr" => true) instead of replacing them.
  202. * By default, attributes are replaced.
  203. *
  204. * @param string $collectionName
  205. * @param mixed|Zend_Cloud_DocumentService_Document $documentId Document ID, adapter-dependent
  206. * @param array|Zend_Cloud_DocumentService_Document $fieldset Set of fields to update
  207. * @param array $options
  208. * @return boolean
  209. */
  210. public function updateDocument($collectionName, $documentId, $fieldset = null, $options = null)
  211. {
  212. if (null === $fieldset && $documentId instanceof Zend_Cloud_DocumentService_Document) {
  213. $fieldset = $documentId->getFields();
  214. if (empty($documentId)) {
  215. $documentId = $documentId->getId();
  216. }
  217. } elseif ($fieldset instanceof Zend_Cloud_DocumentService_Document) {
  218. if (empty($documentId)) {
  219. $documentId = $fieldset->getId();
  220. }
  221. $fieldset = $fieldset->getFields();
  222. }
  223. $replace = array();
  224. if (empty($options[self::MERGE_OPTION])) {
  225. // no merge option - we replace all
  226. foreach ($fieldset as $key => $value) {
  227. $replace[$key] = true;
  228. }
  229. } elseif (is_array($options[self::MERGE_OPTION])) {
  230. foreach ($fieldset as $key => $value) {
  231. if (empty($options[self::MERGE_OPTION][$key])) {
  232. // if there's merge key, we add it, otherwise we replace it
  233. $replace[$key] = true;
  234. }
  235. }
  236. } // otherwise $replace is empty - all is merged
  237. try {
  238. $this->_simpleDb->putAttributes(
  239. $collectionName,
  240. $documentId,
  241. $this->_makeAttributes($documentId, $fieldset),
  242. $replace
  243. );
  244. } catch(Zend_Service_Amazon_Exception $e) {
  245. throw new Zend_Cloud_DocumentService_Exception('Error on document update: '.$e->getMessage(), $e->getCode(), $e);
  246. }
  247. return true;
  248. }
  249. /**
  250. * Delete document.
  251. *
  252. * @param string $collectionName Collection from which to delete document
  253. * @param mixed $document Document ID or Document object.
  254. * @param array $options
  255. * @return boolean
  256. */
  257. public function deleteDocument($collectionName, $document, $options = null)
  258. {
  259. if ($document instanceof Zend_Cloud_DocumentService_Document) {
  260. $document = $document->getId();
  261. }
  262. try {
  263. $this->_simpleDb->deleteAttributes($collectionName, $document);
  264. } catch(Zend_Service_Amazon_Exception $e) {
  265. throw new Zend_Cloud_DocumentService_Exception('Error on document deletion: '.$e->getMessage(), $e->getCode(), $e);
  266. }
  267. return true;
  268. }
  269. /**
  270. * Fetch single document by ID
  271. *
  272. * @param string $collectionName Collection name
  273. * @param mixed $documentId Document ID, adapter-dependent
  274. * @param array $options
  275. * @return Zend_Cloud_DocumentService_Document
  276. */
  277. public function fetchDocument($collectionName, $documentId, $options = null)
  278. {
  279. try {
  280. $attributes = $this->_simpleDb->getAttributes($collectionName, $documentId);
  281. if ($attributes == false || count($attributes) == 0) {
  282. return false;
  283. }
  284. return $this->_resolveAttributes($attributes, true);
  285. } catch(Zend_Service_Amazon_Exception $e) {
  286. throw new Zend_Cloud_DocumentService_Exception('Error on fetching document: '.$e->getMessage(), $e->getCode(), $e);
  287. }
  288. }
  289. /**
  290. * Query for documents stored in the document service. If a string is passed in
  291. * $query, the query string will be passed directly to the service.
  292. *
  293. * @param string $collectionName Collection name
  294. * @param string $query
  295. * @param array $options
  296. * @return array Zend_Cloud_DocumentService_DocumentSet
  297. */
  298. public function query($collectionName, $query, $options = null)
  299. {
  300. $returnDocs = isset($options[self::RETURN_DOCUMENTS])
  301. ? (bool) $options[self::RETURN_DOCUMENTS]
  302. : true;
  303. try {
  304. if ($query instanceof Zend_Cloud_DocumentService_Adapter_SimpleDb_Query) {
  305. $query = $query->assemble($collectionName);
  306. }
  307. $result = $this->_simpleDb->select($query);
  308. } catch(Zend_Service_Amazon_Exception $e) {
  309. throw new Zend_Cloud_DocumentService_Exception('Error on document query: '.$e->getMessage(), $e->getCode(), $e);
  310. }
  311. return $this->_getDocumentSetFromResultSet($result, $returnDocs);
  312. }
  313. /**
  314. * Create query statement
  315. *
  316. * @param string $fields
  317. * @return Zend_Cloud_DocumentService_Adapter_SimpleDb_Query
  318. */
  319. public function select($fields = null)
  320. {
  321. $queryClass = $this->getQueryClass();
  322. if (!class_exists($queryClass)) {
  323. #require_once 'Zend/Loader.php';
  324. Zend_Loader::loadClass($queryClass);
  325. }
  326. $query = new $queryClass($this);
  327. $defaultClass = self::DEFAULT_QUERY_CLASS;
  328. if (!$query instanceof $defaultClass) {
  329. throw new Zend_Cloud_DocumentService_Exception('Query class must extend ' . self::DEFAULT_QUERY_CLASS);
  330. }
  331. $query->select($fields);
  332. return $query;
  333. }
  334. /**
  335. * Get the concrete service client
  336. *
  337. * @return Zend_Service_Amazon_SimpleDb
  338. */
  339. public function getClient()
  340. {
  341. return $this->_simpleDb;
  342. }
  343. /**
  344. * Convert array of key-value pairs to array of Amazon attributes
  345. *
  346. * @param string $name
  347. * @param array $attributes
  348. * @return array
  349. */
  350. protected function _makeAttributes($name, $attributes)
  351. {
  352. $result = array();
  353. foreach ($attributes as $key => $attr) {
  354. $result[] = new Zend_Service_Amazon_SimpleDb_Attribute($name, $key, $attr);
  355. }
  356. return $result;
  357. }
  358. /**
  359. * Convert array of Amazon attributes to array of key-value pairs
  360. *
  361. * @param array $attributes
  362. * @return array
  363. */
  364. protected function _resolveAttributes($attributes, $returnDocument = false)
  365. {
  366. $result = array();
  367. foreach ($attributes as $attr) {
  368. $value = $attr->getValues();
  369. if (count($value) == 0) {
  370. $value = null;
  371. } elseif (count($value) == 1) {
  372. $value = $value[0];
  373. }
  374. $result[$attr->getName()] = $value;
  375. }
  376. // Return as document object?
  377. if ($returnDocument) {
  378. $documentClass = $this->getDocumentClass();
  379. return new $documentClass($result, $attr->getItemName());
  380. }
  381. return $result;
  382. }
  383. /**
  384. * Create suitable document from array of fields
  385. *
  386. * @param array $document
  387. * @return Zend_Cloud_DocumentService_Document
  388. */
  389. protected function _getDocumentFromArray($document)
  390. {
  391. if (!isset($document[Zend_Cloud_DocumentService_Document::KEY_FIELD])) {
  392. if (isset($document[self::ITEM_NAME])) {
  393. $key = $document[self::ITEM_NAME];
  394. unset($document[self::ITEM_NAME]);
  395. } else {
  396. throw new Zend_Cloud_DocumentService_Exception('Fields array should contain the key field '.Zend_Cloud_DocumentService_Document::KEY_FIELD);
  397. }
  398. } else {
  399. $key = $document[Zend_Cloud_DocumentService_Document::KEY_FIELD];
  400. unset($document[Zend_Cloud_DocumentService_Document::KEY_FIELD]);
  401. }
  402. $documentClass = $this->getDocumentClass();
  403. return new $documentClass($document, $key);
  404. }
  405. /**
  406. * Create a DocumentSet from a SimpleDb resultset
  407. *
  408. * @param Zend_Service_Amazon_SimpleDb_Page $resultSet
  409. * @param bool $returnDocs
  410. * @return Zend_Cloud_DocumentService_DocumentSet
  411. */
  412. protected function _getDocumentSetFromResultSet(Zend_Service_Amazon_SimpleDb_Page $resultSet, $returnDocs = true)
  413. {
  414. $docs = array();
  415. foreach ($resultSet->getData() as $item) {
  416. $docs[] = $this->_resolveAttributes($item, $returnDocs);
  417. }
  418. $setClass = $this->getDocumentSetClass();
  419. return new $setClass($docs);
  420. }
  421. }