44
55use Magento \Framework \App \ProductMetadataInterface ;
66use Magento \Framework \App \ResourceConnection ;
7+ use Magento \Framework \Model \ResourceModel \IteratorFactory ;
78use Symfony \Component \Console \Command \Command ;
89use Symfony \Component \Console \Input \InputInterface ;
910use Symfony \Component \Console \Input \InputOption ;
1213
1314class RestoreUseDefaultValueCommand extends Command
1415{
16+ /** @var IteratorFactory */
17+ protected $ iteratorFactory ;
18+
1519 /**
1620 * @var ProductMetaDataInterface
1721 */
@@ -23,11 +27,14 @@ class RestoreUseDefaultValueCommand extends Command
2327 private $ resourceConnection ;
2428
2529 public function __construct (
30+ IteratorFactory $ iteratorFactory ,
2631 ProductMetaDataInterface $ productMetaData ,
2732 ResourceConnection $ resourceConnection ,
2833 string $ name = null
2934 ) {
3035 parent ::__construct ($ name );
36+
37+ $ this ->iteratorFactory = $ iteratorFactory ;
3138 $ this ->productMetaData = $ productMetaData ;
3239 $ this ->resourceConnection = $ resourceConnection ;
3340 }
@@ -58,7 +65,7 @@ public function execute(InputInterface $input, OutputInterface $output): int
5865 if (!in_array ($ entity , ['product ' , 'category ' ])) {
5966 $ output ->writeln ('Please specify the entity with --entity. Possible options are product or category ' );
6067
61- return 1 ;
68+ return 1 ; // error.
6269 }
6370
6471 if (!$ isDryRun && !$ isForce ) {
@@ -76,57 +83,64 @@ public function execute(InputInterface $input, OutputInterface $output): int
7683 }
7784 }
7885
79- $ db = $ this ->resourceConnection ->getConnection ();
86+ $ dbRead = $ this ->resourceConnection ->getConnection ('core_read ' );
87+ $ dbWrite = $ this ->resourceConnection ->getConnection ('core_write ' );
8088 $ counts = [];
8189 $ tables = ['varchar ' , 'int ' , 'decimal ' , 'text ' , 'datetime ' ];
8290 $ column = $ this ->productMetaData ->getEdition () === 'Enterprise ' ? 'row_id ' : 'entity_id ' ;
8391
8492 foreach ($ tables as $ table ) {
8593 // Select all non-global values
8694 $ fullTableName = $ this ->resourceConnection ->getTableName ('catalog_ ' . $ entity . '_entity_ ' . $ table );
87- $ rows = $ db ->fetchAll ('SELECT * FROM ' . $ fullTableName . ' WHERE store_id != 0 ' );
8895
89- foreach ($ rows as $ row ) {
96+ // NULL values are handled separately
97+ $ query = $ dbRead ->query ("SELECT * FROM $ fullTableName WHERE store_id != 0 AND value IS NOT NULL " );
98+
99+ $ iterator = $ this ->iteratorFactory ->create ();
100+ $ iterator ->walk ($ query , [function (array $ result ) use ($ column , &$ counts , $ dbRead , $ dbWrite , $ fullTableName , $ isDryRun , $ output ): void {
101+ $ row = $ result ['row ' ];
102+
90103 // Select the global value if it's the same as the non-global value
91- $ results = $ db -> fetchAll (
104+ $ query = $ dbRead -> query (
92105 'SELECT * FROM ' . $ fullTableName
93106 . ' WHERE attribute_id = ? AND store_id = ? AND ' . $ column . ' = ? AND BINARY value = ? ' ,
94107 [$ row ['attribute_id ' ], 0 , $ row [$ column ], $ row ['value ' ]]
95108 );
96109
97- if (count ($ results ) > 0 ) {
98- foreach ($ results as $ result ) {
99- if (!$ isDryRun ) {
100- // Remove the non-global value
101- $ db ->query (
102- 'DELETE FROM ' . $ fullTableName . ' WHERE value_id = ? ' ,
103- $ row ['value_id ' ]
104- );
105- }
106-
107- $ output ->writeln (
108- 'Deleting value ' . $ row ['value_id ' ] . ' " ' . $ row ['value ' ] . '" in favor of '
109- . $ result ['value_id ' ]
110- . ' for attribute ' . $ row ['attribute_id ' ] . ' in table ' . $ fullTableName
110+ $ iterator = $ this ->iteratorFactory ->create ();
111+ $ iterator ->walk ($ query , [function (array $ result ) use (&$ counts , $ dbWrite , $ fullTableName , $ isDryRun , $ output , $ row ): void {
112+ $ result = $ result ['row ' ];
113+
114+ if (!$ isDryRun ) {
115+ // Remove the non-global value
116+ $ dbWrite ->query (
117+ 'DELETE FROM ' . $ fullTableName . ' WHERE value_id = ? ' ,
118+ $ row ['value_id ' ]
111119 );
120+ }
112121
113- if (!isset ($ counts [$ row ['attribute_id ' ]])) {
114- $ counts [$ row ['attribute_id ' ]] = 0 ;
115- }
122+ $ output ->writeln (
123+ 'Deleting value ' . $ row ['value_id ' ] . ' " ' . $ row ['value ' ] . '" in favor of '
124+ . $ result ['value_id ' ]
125+ . ' for attribute ' . $ row ['attribute_id ' ] . ' in table ' . $ fullTableName
126+ );
116127
117- $ counts [$ row ['attribute_id ' ]]++;
128+ if (!isset ($ counts [$ row ['attribute_id ' ]])) {
129+ $ counts [$ row ['attribute_id ' ]] = 0 ;
118130 }
119- }
120- }
121131
122- $ nullValues = $ db ->fetchOne (
132+ $ counts [$ row ['attribute_id ' ]]++;
133+ }]);
134+ }]);
135+
136+ $ nullCount = (int ) $ dbRead ->fetchOne (
123137 'SELECT COUNT(*) FROM ' . $ fullTableName . ' WHERE store_id != 0 AND value IS NULL '
124138 );
125139
126- if (!$ isDryRun && $ nullValues > 0 ) {
127- $ output ->writeln ("Deleting " . $ nullValues . " NULL value(s) from " . $ fullTableName );
140+ if (!$ isDryRun && $ nullCount > 0 ) {
141+ $ output ->writeln ("Deleting $ nullCount NULL value(s) from $ fullTableName" );
128142 // Remove all non-global null values
129- $ db ->query (
143+ $ dbWrite ->query (
130144 'DELETE FROM ' . $ fullTableName . ' WHERE store_id != 0 AND value IS NULL '
131145 );
132146 }
0 commit comments