SaveMultiple.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\Inventory\Model\ResourceModel\SourceItem;
  8. use Magento\Framework\App\ResourceConnection;
  9. use Magento\Inventory\Model\ResourceModel\SourceItem as SourceItemResourceModel;
  10. use Magento\InventoryApi\Api\Data\SourceItemInterface;
  11. /**
  12. * Implementation of SourceItem save multiple operation for specific db layer
  13. * Save Multiple used here for performance efficient purposes over single save operation
  14. */
  15. class SaveMultiple
  16. {
  17. /**
  18. * @var ResourceConnection
  19. */
  20. private $resourceConnection;
  21. /**
  22. * @param ResourceConnection $resourceConnection
  23. */
  24. public function __construct(
  25. ResourceConnection $resourceConnection
  26. ) {
  27. $this->resourceConnection = $resourceConnection;
  28. }
  29. /**
  30. * Multiple save source items
  31. *
  32. * @param SourceItemInterface[] $sourceItems
  33. * @return void
  34. */
  35. public function execute(array $sourceItems)
  36. {
  37. if (!count($sourceItems)) {
  38. return;
  39. }
  40. $connection = $this->resourceConnection->getConnection();
  41. $tableName = $this->resourceConnection->getTableName(SourceItemResourceModel::TABLE_NAME_SOURCE_ITEM);
  42. $columnsSql = $this->buildColumnsSqlPart([
  43. SourceItemInterface::SOURCE_CODE,
  44. SourceItemInterface::SKU,
  45. SourceItemInterface::QUANTITY,
  46. SourceItemInterface::STATUS
  47. ]);
  48. $valuesSql = $this->buildValuesSqlPart($sourceItems);
  49. $onDuplicateSql = $this->buildOnDuplicateSqlPart([
  50. SourceItemInterface::QUANTITY,
  51. SourceItemInterface::STATUS,
  52. ]);
  53. $bind = $this->getSqlBindData($sourceItems);
  54. $insertSql = sprintf(
  55. 'INSERT INTO `%s` (%s) VALUES %s %s',
  56. $tableName,
  57. $columnsSql,
  58. $valuesSql,
  59. $onDuplicateSql
  60. );
  61. $connection->query($insertSql, $bind);
  62. }
  63. /**
  64. * @param array $columns
  65. * @return string
  66. */
  67. private function buildColumnsSqlPart(array $columns): string
  68. {
  69. $connection = $this->resourceConnection->getConnection();
  70. $processedColumns = array_map([$connection, 'quoteIdentifier'], $columns);
  71. $sql = implode(', ', $processedColumns);
  72. return $sql;
  73. }
  74. /**
  75. * @param SourceItemInterface[] $sourceItems
  76. * @return string
  77. */
  78. private function buildValuesSqlPart(array $sourceItems): string
  79. {
  80. $sql = rtrim(str_repeat('(?, ?, ?, ?), ', count($sourceItems)), ', ');
  81. return $sql;
  82. }
  83. /**
  84. * @param SourceItemInterface[] $sourceItems
  85. * @return array
  86. */
  87. private function getSqlBindData(array $sourceItems): array
  88. {
  89. $bind = [];
  90. foreach ($sourceItems as $sourceItem) {
  91. $bind = array_merge($bind, [
  92. $sourceItem->getSourceCode(),
  93. $sourceItem->getSku(),
  94. $sourceItem->getQuantity(),
  95. $sourceItem->getStatus(),
  96. ]);
  97. }
  98. return $bind;
  99. }
  100. /**
  101. * @param array $fields
  102. * @return string
  103. */
  104. private function buildOnDuplicateSqlPart(array $fields): string
  105. {
  106. $connection = $this->resourceConnection->getConnection();
  107. $processedFields = [];
  108. foreach ($fields as $field) {
  109. $processedFields[] = sprintf('%1$s = VALUES(%1$s)', $connection->quoteIdentifier($field));
  110. }
  111. $sql = 'ON DUPLICATE KEY UPDATE ' . implode(', ', $processedFields);
  112. return $sql;
  113. }
  114. }