10
10
use Magento \Catalog \Api \CategoryRepositoryInterface ;
11
11
use Magento \Catalog \Api \Data \CategoryInterface ;
12
12
use Magento \Catalog \Model \Category ;
13
+ use Magento \Framework \App \ResourceConnection ;
14
+ use Magento \Framework \DB \Adapter \AdapterInterface ;
15
+ use Magento \Framework \Exception \NoSuchEntityException ;
13
16
use Magento \Store \Model \StoreManagerInterface ;
14
17
15
18
/**
16
19
* @magentoAppArea adminhtml
17
20
*/
18
21
class SaveCategoryDifferentScopesTest extends AbstractSaveCategoryTest
19
22
{
20
- private const DEFAULT_STORE_ID = 1 ;
21
- private const FIXTURE_CATEGORY_ID = 333 ;
22
23
private const GLOBAL_SCOPE_ID = 0 ;
23
-
24
- private const FIXTURE_URL_KEY = 'category-1 ' ;
24
+ private const DEFAULT_STORE_ID = 1 ;
25
25
26
26
private const FIXTURE_CATEGORY_ROOT = 400 ;
27
27
private const FIXTURE_CATEGORY_CHILD = 401 ;
@@ -35,6 +35,9 @@ class SaveCategoryDifferentScopesTest extends AbstractSaveCategoryTest
35
35
/** @var StoreManagerInterface */
36
36
private $ storeManager ;
37
37
38
+ /** @var AdapterInterface */
39
+ private $ dbConnection ;
40
+
38
41
/**
39
42
* @inheritDoc
40
43
*/
@@ -43,6 +46,8 @@ protected function setUp()
43
46
parent ::setUp ();
44
47
$ this ->categoryRepository = $ this ->_objectManager ->get (CategoryRepositoryInterface::class);
45
48
$ this ->storeManager = $ this ->_objectManager ->get (StoreManagerInterface::class);
49
+
50
+
46
51
}
47
52
48
53
/**
@@ -55,53 +60,117 @@ protected function tearDown()
55
60
parent ::tearDown ();
56
61
}
57
62
63
+ /**
64
+ * For Test purposes you may need FRESH Category repository without internal cache
65
+ *
66
+ * @return CategoryRepositoryInterface
67
+ */
68
+ private function createCategoryRepository (): CategoryRepositoryInterface
69
+ {
70
+ return $ this ->_objectManager ->create (CategoryRepositoryInterface::class);
71
+ }
72
+
58
73
/**
59
74
* Change of `url_key` for specific store should not affect global value of `url_path`
60
75
*
61
76
* @magentoDbIsolation enabled
62
- * @magentoDataFixture Magento/Catalog/_files/category.php
77
+ * @magentoDataFixture Magento/Catalog/_files/category_tree.php
78
+ * @magentoDataFixture Magento/Store/_files/core_fixturestore.php
63
79
*/
64
- public function testChangeUrlKeyForSpecificStoreShouldNotChangeGlobalUrlPath ()
80
+ public function testUrlKeyUpdateInCustomStoreDoesNotChangeGlobalUrlPath ()
65
81
{
66
- $ expectedStoreScopeUrlKey = 'url-key-store-1 ' ;
67
- $ expectedGlobalScopeUrlKey = self ::FIXTURE_URL_KEY ;
82
+ $ secondStoreId = $ this ->getStoreId (self ::FIXTURE_SECOND_STORE_CODE );
83
+
84
+ $ storeScopeUrlKey = 'url-key-store-1 ' ;
68
85
69
- $ postData = [
70
- 'entity_id ' => self ::FIXTURE_CATEGORY_ID ,
71
- 'store_id ' => self ::DEFAULT_STORE_ID ,
72
- 'url_key ' => $ expectedStoreScopeUrlKey
86
+ $ updateCategoryStoreScope = [
87
+ 'entity_id ' => self ::FIXTURE_CATEGORY_LEAF ,
88
+ 'store_id ' => $ secondStoreId ,
89
+ 'url_key ' => $ storeScopeUrlKey ,
90
+ 'use_config ' => [
91
+ 'available_sort_by ' => 1 ,
92
+ ]
73
93
];
74
- $ responseData = $ this ->performSaveCategoryRequest ($ postData );
94
+ $ responseData = $ this ->performSaveCategoryRequest ($ updateCategoryStoreScope );
75
95
$ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
76
96
77
- /** @var CategoryInterface|Category $storeScopeCategory */
78
- $ storeScopeCategory = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_ID , self ::DEFAULT_STORE_ID );
79
- $ this ->assertSame ($ expectedStoreScopeUrlKey , $ storeScopeCategory ->getData ('url_path ' ));
97
+ $ this ->assertCategoryUrlPathForStore (
98
+ self ::FIXTURE_CATEGORY_LEAF ,
99
+ $ secondStoreId ,
100
+ $ this ->getExpectedUrlPath ([2 => $ storeScopeUrlKey ])
101
+ );
80
102
81
- $ globalScopeCategory = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_ID , self ::GLOBAL_SCOPE_ID );
82
- $ this ->assertSame ($ expectedGlobalScopeUrlKey , $ globalScopeCategory ->getData ('url_path ' ));
103
+ $ this ->assertCategoryUrlPathForStore (
104
+ self ::FIXTURE_CATEGORY_LEAF ,
105
+ self ::GLOBAL_SCOPE_ID ,
106
+ $ this ->getExpectedUrlPath ()
107
+ );
83
108
}
84
109
85
110
/**
86
- * Change of `url_key` for root category in specific store should change all the children `url_path`
111
+ * Magento EAV should not create entries for Default store (1) when Custom Store values are saved
87
112
*
88
113
* @magentoDbIsolation enabled
89
114
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
90
115
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
91
116
*/
92
- public function testChangeUrlKeyAffectsAllChildrenUrlPath ()
117
+ public function testUrlKeyUpdateInCustomStoreDoesNotCreateEntriesForDefaultStore ()
93
118
{
94
119
$ secondStoreId = $ this ->getStoreId (self ::FIXTURE_SECOND_STORE_CODE );
120
+ $ storeScopeUrlKey = 'url-key-store-1 ' ;
95
121
96
- $ urlKeys = [
97
- 1 => 'category-1 ' ,
98
- 2 => 'category-1-1 ' ,
99
- 3 => 'category-1-1-1 '
122
+ $ updateCategoryStoreScope = [
123
+ 'entity_id ' => self ::FIXTURE_CATEGORY_LEAF ,
124
+ 'store_id ' => $ secondStoreId ,
125
+ 'url_key ' => $ storeScopeUrlKey ,
126
+ 'use_config ' => [
127
+ 'available_sort_by ' => 1 ,
128
+ ]
100
129
];
130
+ $ responseData = $ this ->performSaveCategoryRequest ($ updateCategoryStoreScope );
131
+ $ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
132
+
133
+ $ attributeValues = $ this ->getCategoryVarcharAttributeValuesPerScope (self ::FIXTURE_CATEGORY_LEAF , 'url_path ' );
134
+ $ this ->assertArrayNotHasKey (self ::DEFAULT_STORE_ID , $ attributeValues );
135
+ }
101
136
102
- /** @var CategoryInterface|Category $leafOriginal */
103
- $ leafOriginal = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_LEAF );
104
- $ this ->assertSame (implode ('/ ' , $ urlKeys ), $ leafOriginal ->getData ('url_path ' ));
137
+ /**
138
+ * Magento EAV should not create entries for Default store (1) when Global scope (0) values are saved
139
+ *
140
+ * @magentoDbIsolation enabled
141
+ * @magentoDataFixture Magento/Catalog/_files/category_tree.php
142
+ * @magentoDataFixture Magento/Store/_files/core_fixturestore.php
143
+ */
144
+ public function testUrlKeyUpdateInGlobalScopeDoesNotCreateEntriesForDefaultStore ()
145
+ {
146
+ $ storeScopeUrlKey = 'url-key-store-1 ' ;
147
+
148
+ $ updateCategoryStoreScope = [
149
+ 'entity_id ' => self ::FIXTURE_CATEGORY_LEAF ,
150
+ 'url_key ' => $ storeScopeUrlKey ,
151
+ 'use_config ' => [
152
+ 'available_sort_by ' => 1 ,
153
+ ]
154
+ ];
155
+ $ responseData = $ this ->performSaveCategoryRequest ($ updateCategoryStoreScope );
156
+ $ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
157
+
158
+ $ attributeValues = $ this ->getCategoryVarcharAttributeValuesPerScope (self ::FIXTURE_CATEGORY_LEAF , 'url_path ' );
159
+ $ this ->assertArrayNotHasKey (self ::DEFAULT_STORE_ID , $ attributeValues );
160
+ }
161
+
162
+ /**
163
+ * Change of `url_key` for root category in specific store should change all the children `url_path`
164
+ *
165
+ * @magentoDbIsolation enabled
166
+ * @magentoDataFixture Magento/Catalog/_files/category_tree.php
167
+ * @magentoDataFixture Magento/Store/_files/core_fixturestore.php
168
+ */
169
+ public function testUpdateRootUrlKeyAffectsAllChildrenUrlPath ()
170
+ {
171
+ $ secondStoreId = $ this ->getStoreId (self ::FIXTURE_SECOND_STORE_CODE );
172
+
173
+ $ this ->assertCategoryUrlPathForStore (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId , $ this ->getExpectedUrlPath ());
105
174
106
175
$ updateRootData = [
107
176
'entity_id ' => self ::FIXTURE_CATEGORY_ROOT ,
@@ -114,16 +183,13 @@ public function testChangeUrlKeyAffectsAllChildrenUrlPath()
114
183
$ responseData = $ this ->performSaveCategoryRequest ($ updateRootData );
115
184
$ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
116
185
117
- $ newUrlKeys = $ urlKeys ;
118
- $ newUrlKeys [1 ] = 'store-root ' ;
119
-
120
- /** @var CategoryInterface|Category $leafStoreScope */
121
- $ leafStoreScope = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId );
122
- $ this ->assertSame (implode ('/ ' , $ newUrlKeys ), $ leafStoreScope ->getData ('url_path ' ));
186
+ $ this ->categoryRepository = $ this ->createCategoryRepository ();
187
+ $ this ->assertCategoryUrlPathForStore (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId ,
188
+ $ this ->getExpectedUrlPath ([0 => 'store-root ' ]));
123
189
124
- /** @var CategoryInterface|Category $leafGlobalScope */
125
- $ leafGlobalScope = $ this ->categoryRepository -> get (self ::FIXTURE_CATEGORY_LEAF );
126
- $ this -> assertSame ( implode ( ' / ' , $ urlKeys ), $ leafGlobalScope -> getData ( ' url_path ' ));
190
+ // Verify the potential side effects to Global Scope
191
+ $ this ->assertCategoryUrlPathForStore (self ::FIXTURE_CATEGORY_LEAF , self :: DEFAULT_STORE_ID ,
192
+ $ this -> getExpectedUrlPath ( ));
127
193
}
128
194
129
195
/**
@@ -133,24 +199,27 @@ public function testChangeUrlKeyAffectsAllChildrenUrlPath()
133
199
* @magentoDataFixture Magento/Store/_files/core_fixturestore.php
134
200
* @magentoDataFixture Magento/Catalog/_files/category_tree.php
135
201
*/
136
- public function testCategoryUrlPathUsesGlobalUrlKey ()
202
+ public function testStoreScopeCategoryUrlPathUsesGlobalScopeUrlKey ()
137
203
{
204
+ $ this ->markTestIncomplete ('Still in Magento ' );
138
205
$ secondStoreId = $ this ->getStoreId (self ::FIXTURE_SECOND_STORE_CODE );
139
206
140
- $ setSecondStoreCategoryUrlKey = [
207
+ $ updateSecondStoreCategoryUrlKey = [
141
208
'entity_id ' => self ::FIXTURE_CATEGORY_CHILD ,
142
209
'url_key ' => 'second-store-child ' ,
143
210
'store_id ' => $ secondStoreId ,
144
211
'use_config ' => [
145
212
'available_sort_by ' => 1 ,
146
213
]
147
214
];
148
- $ responseData = $ this ->performSaveCategoryRequest ($ setSecondStoreCategoryUrlKey );
215
+ $ responseData = $ this ->performSaveCategoryRequest ($ updateSecondStoreCategoryUrlKey );
149
216
$ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
150
217
151
- /** @var CategoryInterface|Category $categoryWithCustomUrlKey */
152
- $ categoryWithCustomUrlKey = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_CHILD , $ secondStoreId );
153
- $ this ->assertSame ('category-1/second-store-child ' , $ categoryWithCustomUrlKey ->getData ('url_path ' ));
218
+ // Temporary solution to reset Request object.
219
+ $ this ->getRequest ()->setDispatched (false );
220
+
221
+ $ this ->assertCategoryUrlPathForStore (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId ,
222
+ $ this ->getExpectedUrlPath ([1 => 'second-store-child ' ]));
154
223
155
224
$ useDefaultUrlKey = [
156
225
'entity_id ' => self ::FIXTURE_CATEGORY_CHILD ,
@@ -165,19 +234,81 @@ public function testCategoryUrlPathUsesGlobalUrlKey()
165
234
$ responseData = $ this ->performSaveCategoryRequest ($ useDefaultUrlKey );
166
235
$ this ->assertRequestIsSuccessfullyPerformed ($ responseData );
167
236
168
- $ categoryWithDefaultUrlKey = $ this ->categoryRepository ->get (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId );
169
- $ this ->assertSame ('category-1/category-1-1/category-1-1-1 ' , $ categoryWithDefaultUrlKey ->getData ('url_path ' ));
237
+ $ this ->assertCategoryUrlPathForStore (self ::FIXTURE_CATEGORY_LEAF , $ secondStoreId , $ this ->getExpectedUrlPath ());
170
238
}
171
239
172
240
/**
173
241
* Returns StoreID by Code
174
242
*
175
243
* @param string $code
176
244
* @return int
177
- * @throws \Magento\Framework\Exception\ NoSuchEntityException
245
+ * @throws NoSuchEntityException
178
246
*/
179
247
private function getStoreId (string $ code ): int
180
248
{
181
249
return (int )$ this ->storeManager ->getStore ($ code )->getId ();
182
250
}
251
+
252
+ /**
253
+ * Returns
254
+ * @param array $replacements
255
+ * @return string
256
+ */
257
+ private function getExpectedUrlPath (array $ replacements = []): string
258
+ {
259
+ $ basicUrlPath = ['category-1 ' , 'category-1-1 ' , 'category-1-1-1 ' ];
260
+
261
+ return implode ('/ ' , array_replace ($ basicUrlPath , $ replacements ));
262
+ }
263
+
264
+ /**
265
+ * Returns array of attribute values per scope
266
+ *
267
+ * @param int $categoryId
268
+ * @param string $attributeCode
269
+ */
270
+ private function getCategoryVarcharAttributeValuesPerScope (int $ categoryId , string $ attributeCode )
271
+ {
272
+ $ selectValues = $ this ->getConnection ()->select ()
273
+ ->from (
274
+ ['ccev ' => $ this ->getConnection ()->getTableName ('catalog_category_entity_varchar ' )],
275
+ ['store_id ' , 'value ' ]
276
+ )
277
+ ->join (
278
+ ['ea ' => $ this ->getConnection ()->getTableName ('eav_attribute ' )],
279
+ 'ccev.attribute_id = ea.attribute_id ' ,
280
+ []
281
+ )
282
+ ->where ('entity_id = ? ' , $ categoryId )
283
+ ->where ('ea.attribute_code = ? ' , $ attributeCode );
284
+
285
+ return $ this ->getConnection ()->fetchPairs ($ selectValues );
286
+ }
287
+
288
+ /**
289
+ * Asserts the URL path for the Category in specified Store scope
290
+ *
291
+ * @param int $categoryId
292
+ * @param int $storeId
293
+ * @param string $expectedPath
294
+ * @throws NoSuchEntityException
295
+ */
296
+ private function assertCategoryUrlPathForStore (int $ categoryId , int $ storeId , string $ expectedPath )
297
+ {
298
+ /** @var CategoryInterface|Category $storeScopeCategory */
299
+ $ storeScopeCategory = $ this ->categoryRepository ->get ($ categoryId , $ storeId );
300
+ $ this ->assertSame ($ storeId , $ storeScopeCategory ->getStoreId ());
301
+ $ this ->assertSame ($ expectedPath , $ storeScopeCategory ->getData ('url_path ' ));
302
+ }
303
+
304
+ private function getConnection (): AdapterInterface
305
+ {
306
+ if (null === $ this ->dbConnection ) {
307
+ /** @var ResourceConnection $resourceConnection */
308
+ $ resourceConnection = $ this ->_objectManager ->create (ResourceConnection::class);
309
+ $ this ->dbConnection = $ resourceConnection ->getConnection ();
310
+ }
311
+
312
+ return $ this ->dbConnection ;
313
+ }
183
314
}
0 commit comments