Skip to content

Commit 07d31d2

Browse files
authored
Merge pull request #28 from tuyennn/feature/remove-raw-mysql-queries
[feat] Remove all raw mysql queries
2 parents 3e18c33 + 546529d commit 07d31d2

5 files changed

+449
-211
lines changed

Console/Command/CleanUpAttributesAndValuesWithoutParentCommand.php

+53-19
Original file line numberDiff line numberDiff line change
@@ -25,78 +25,112 @@ class CleanUpAttributesAndValuesWithoutParentCommand extends Command
2525
*/
2626
private $eavEntityTypeCollectionFactory;
2727

28+
/**
29+
* Constructor
30+
*
31+
* @param ResourceConnection $resourceConnection
32+
* @param EavEntityTypeCollectionFactory $eavEntityTypeCollectionFactory
33+
* @param string|null $name
34+
*/
2835
public function __construct(
2936
ResourceConnection $resourceConnection,
3037
EavEntityTypeCollectionFactory $eavEntityTypeCollectionFactory,
3138
string $name = null
3239
) {
3340
parent::__construct($name);
34-
$this->resourceConnection = $resourceConnection;
41+
$this->resourceConnection = $resourceConnection;
3542
$this->eavEntityTypeCollectionFactory = $eavEntityTypeCollectionFactory;
3643
}
3744

45+
/**
46+
* @inheritdoc
47+
*/
3848
protected function configure()
3949
{
40-
$description
41-
= 'Remove orphaned attribute values - those which are missing a parent entry (with the corresponding backend_type) in eav_attribute';
50+
//phpcs:ignore Generic.Files.LineLength.TooLong
51+
$description = 'Remove orphaned attribute values - those which are missing a parent entry (with the corresponding backend_type) in eav_attribute';
4252
$this
4353
->setName('eav:clean:attributes-and-values-without-parent')
4454
->setDescription($description)
4555
->addOption('dry-run')
4656
->addOption('force');
4757
}
4858

59+
/**
60+
* @inheritdoc
61+
*/
4962
public function execute(InputInterface $input, OutputInterface $output): int
5063
{
5164
$isDryRun = $input->getOption('dry-run');
5265
$isForce = $input->getOption('force');
5366

5467
if (!$isDryRun && !$isForce) {
5568
if (!$input->isInteractive()) {
56-
$output->writeln('ERROR: neither --dry-run nor --force options were supplied, and we are not running interactively.');
57-
58-
return 1; // error.
69+
$output->writeln(
70+
'<error>'
71+
//phpcs:ignore Generic.Files.LineLength.TooLong
72+
. 'ERROR: neither --dry-run nor --force options were supplied, and we are not running interactively.'
73+
. '</error>'
74+
);
75+
76+
return Command::FAILURE;
5977
}
6078

61-
$output->writeln('WARNING: this is not a dry run. If you want to do a dry-run, add --dry-run.');
79+
$output->writeln(
80+
'<info>WARNING: this is not a dry run. If you want to do a dry-run, add --dry-run.</info>'
81+
);
6282
$question = new ConfirmationQuestion('Are you sure you want to continue? [No] ', false);
6383

6484
if (!$this->getHelper('question')->ask($input, $output, $question)) {
65-
return 1; // error.
85+
return Command::FAILURE;
6686
}
6787
}
6888

69-
$db = $this->resourceConnection->getConnection();
70-
$types = ['varchar', 'int', 'decimal', 'text', 'datetime'];
89+
$db = $this->resourceConnection->getConnection();
90+
$types = ['varchar', 'int', 'decimal', 'text', 'datetime'];
7191
$entityTypeCodes = [
7292
ProductAttributeInterface::ENTITY_TYPE_CODE,
7393
CategoryAttributeInterface::ENTITY_TYPE_CODE,
7494
CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
7595
AddressMetadataInterface::ENTITY_TYPE_ADDRESS
7696
];
7797

98+
$eavTable = $db->getTableName('eav_attribute');
99+
78100
foreach ($entityTypeCodes as $code) {
79101
$entityType = $this->eavEntityTypeCollectionFactory
80102
->create()
81103
->addFieldToFilter('entity_type_code', $code)
82104
->getFirstItem();
83-
$output->writeln("<info>Cleaning values for $code</info>");
105+
$output->writeln('<info>' . sprintf('Cleaning values for %s', $code) . '</info>');
84106

85107
foreach ($types as $type) {
86-
$eavTable = $this->resourceConnection->getTableName('eav_attribute');
87-
$entityValueTable = $this->resourceConnection->getTableName($code . '_entity_' . $type);
88-
$query = "SELECT COUNT(*) FROM $entityValueTable WHERE `attribute_id` NOT IN(SELECT attribute_id"
89-
. " FROM `$eavTable` WHERE entity_type_id = " . $entityType->getEntityTypeId() . " AND backend_type = '$type')";
90-
$count = (int) $db->fetchOne($query);
108+
$entityValueTable = $this->resourceConnection->getTableName(sprintf('%s_entity_%s', $code, $type));
109+
110+
$select = $db->select()
111+
->from($entityValueTable, ['COUNT(*)'])
112+
->where('attribute_id NOT IN (?)', new \Zend_Db_Expr(
113+
$db->select()
114+
->from($eavTable, ['attribute_id'])
115+
->where('entity_type_id = ?', $entityType->getEntityTypeId())
116+
->where('backend_type = ?', $type)
117+
));
118+
$count = (int)$db->fetchOne($select);
91119
$output->writeln("Clean up $count rows in $entityValueTable");
92120

93121
if (!$isDryRun && $count > 0) {
94-
$db->query("DELETE FROM $entityValueTable WHERE `attribute_id` NOT IN(SELECT attribute_id"
95-
. " FROM `$eavTable` WHERE entity_type_id = " . $entityType->getEntityTypeId() . " AND backend_type = '$type')");
122+
$db->delete($entityValueTable, [
123+
'attribute_id NOT IN (?)' => new \Zend_Db_Expr(
124+
$db->select()
125+
->from($eavTable, ['attribute_id'])
126+
->where('entity_type_id = ?', $entityType->getEntityTypeId())
127+
->where('backend_type = ?', $type)
128+
)
129+
]);
96130
}
97131
}
98132
}
99133

100-
return 0; // success.
134+
return Command::SUCCESS;
101135
}
102136
}

Console/Command/RemoveUnusedAttributesCommand.php

+58-28
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,29 @@ class RemoveUnusedAttributesCommand extends Command
2828
*/
2929
private $searchCriteriaBuilderFactory;
3030

31+
/**
32+
* Constructor
33+
*
34+
* @param ResourceConnection $resourceConnection
35+
* @param AttributeRepositoryInterface $attributeRepository
36+
* @param SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
37+
* @param string|null $name
38+
*/
3139
public function __construct(
3240
ResourceConnection $resourceConnection,
3341
AttributeRepositoryInterface $attributeRepository,
3442
SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
3543
string $name = null
3644
) {
3745
parent::__construct($name);
38-
$this->resourceConnection = $resourceConnection;
39-
$this->attributeRepository = $attributeRepository;
46+
$this->resourceConnection = $resourceConnection;
47+
$this->attributeRepository = $attributeRepository;
4048
$this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
4149
}
4250

51+
/**
52+
* @inheritdoc
53+
*/
4354
protected function configure()
4455
{
4556
$this
@@ -49,76 +60,95 @@ protected function configure()
4960
->addOption('force');
5061
}
5162

63+
/**
64+
* @inheritdoc
65+
*/
5266
public function execute(InputInterface $input, OutputInterface $output): int
5367
{
5468
$isDryRun = $input->getOption('dry-run');
5569
$isForce = $input->getOption('force');
5670

5771
if (!$isDryRun && !$isForce) {
5872
if (!$input->isInteractive()) {
59-
$output->writeln('ERROR: neither --dry-run nor --force options were supplied, and we are not running interactively.');
60-
61-
return 1; // error.
73+
$output->writeln(
74+
'<error>'
75+
//phpcs:ignore Generic.Files.LineLength.TooLong
76+
. 'ERROR: neither --dry-run nor --force options were supplied, and we are not running interactively.'
77+
. '</error>'
78+
);
79+
80+
return Command::FAILURE;
6281
}
6382

64-
$output->writeln('WARNING: this is not a dry run. If you want to do a dry-run, add --dry-run.');
83+
$output->writeln(
84+
'<info>WARNING: this is not a dry run. If you want to do a dry-run, add --dry-run.</info>'
85+
);
6586
$question = new ConfirmationQuestion('Are you sure you want to continue? [No] ', false);
6687

6788
if (!$this->getHelper('question')->ask($input, $output, $question)) {
68-
return 1; // error.
89+
return Command::FAILURE;
6990
}
7091
}
7192

72-
$db = $this->resourceConnection->getConnection('core_write');
73-
$deleted = 0;
74-
$searchCriteria = $this->searchCriteriaBuilderFactory->create()
93+
$db = $this->resourceConnection->getConnection('core_write');
94+
95+
$searchCriteria = $this->searchCriteriaBuilderFactory->create()
7596
->addFilter('is_user_defined', 1)
7697
->addFilter('backend_type', 'static', 'neq')
7798
->create();
78-
$attributes = $this->attributeRepository
99+
$attributes = $this->attributeRepository
79100
->getList(ProductAttributeInterface::ENTITY_TYPE_CODE, $searchCriteria)
80101
->getItems();
81-
$eavAttributeTable = $this->resourceConnection->getTableName('eav_attribute');
102+
$eavAttributeTable = $this->resourceConnection->getTableName('eav_attribute');
82103
$eavEntityAttributeTable = $this->resourceConnection->getTableName('eav_entity_attribute');
83104

105+
$deleted = 0;
84106
foreach ($attributes as $attribute) {
85-
$table = $this->resourceConnection->getTableName('catalog_product_entity_' . $attribute->getBackendType());
107+
$table = $this->resourceConnection
108+
->getTableName(sprintf('catalog_product_entity_%s', $attribute->getBackendType()));
86109
/* Look for attributes that have no values set in products */
87-
$attributeValues = (int)$db->fetchOne('SELECT COUNT(*) FROM ' . $table . ' WHERE attribute_id = ?',
88-
[$attribute->getAttributeId()]);
110+
$select = $db->select()
111+
->from($table, ['COUNT(*)'])
112+
->where('attribute_id = ?', $attribute->getAttributeId());
113+
$attributeValues = (int)$db->fetchOne($select);
89114

90115
if ($attributeValues === 0) {
91-
$output->writeln($attribute->getAttributeCode() . ' has ' . $attributeValues
92-
. ' values; deleting attribute');
116+
$output->writeln(
117+
sprintf('%s has %d values; deleting attribute', $attribute->getAttributeCode(), $attributeValues)
118+
);
93119

94120
if (!$isDryRun) {
95-
$db->query('DELETE FROM ' . $eavAttributeTable . ' WHERE attribute_code = ?',
96-
$attribute->getAttributeCode());
121+
$db->delete($eavAttributeTable, ['attribute_code = ?' => $attribute->getAttributeCode()]);
97122
}
98123

99124
$deleted++;
100125
} else {
101126
/* Look for attributes that are not assigned to attribute sets */
102-
$attributeGroups = (int)$db->fetchOne('SELECT COUNT(*) FROM ' . $eavEntityAttributeTable
103-
. ' WHERE attribute_id = ?', [$attribute->getAttributeId()]);
127+
$select = $db->select()
128+
->from($eavEntityAttributeTable, ['COUNT(*)'])
129+
->where('attribute_id = ?', $attribute->getAttributeId());
130+
$attributeGroups = (int)$db->fetchOne($select);
104131

105132
if ($attributeGroups === 0) {
106-
$output->writeln($attribute->getAttributeCode()
107-
. ' is not assigned to any attribute set; deleting attribute and its ' . $attributeValues
108-
. ' orphaned value(s)');
133+
$output->writeln(
134+
sprintf(
135+
'%s is not assigned to any attribute set; deleting attribute and its %d orphaned value(s)',
136+
$attribute->getAttributeCode(),
137+
$attributeValues
138+
)
139+
);
109140

110141
if (!$isDryRun) {
111-
$db->query('DELETE FROM ' . $eavAttributeTable . ' WHERE attribute_code = ?',
112-
$attribute->getAttributeCode());
142+
$db->delete($eavAttributeTable, ['attribute_code = ?' => $attribute->getAttributeCode()]);
113143
}
114144

115145
$deleted++;
116146
}
117147
}
118148
}
119149

120-
$output->writeln('Deleted ' . $deleted . ' attributes.');
150+
$output->writeln(sprintf('Deleted %d attributes.', $deleted));
121151

122-
return 0; // success.
152+
return Command::SUCCESS;
123153
}
124154
}

0 commit comments

Comments
 (0)