Skip to content

Commit 581c0e6

Browse files
author
Prabhu Ram
committed
Merge remote-tracking branch 'origin/MC-29929-cms-blocks' into MC-21228
2 parents c40f8ae + a3fab20 commit 581c0e6

File tree

12 files changed

+517
-20
lines changed

12 files changed

+517
-20
lines changed

app/code/Magento/CatalogCmsGraphQl/Model/Resolver/Category/Block.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Framework\Exception\LocalizedException;
1212
use Magento\Framework\Exception\NoSuchEntityException;
1313
use Magento\Framework\GraphQl\Config\Element\Field;
14+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1415
use Magento\Framework\GraphQl\Query\ResolverInterface;
1516
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1617
use Magento\CmsGraphQl\Model\Resolver\DataProvider\Block as BlockProvider;
@@ -48,18 +49,19 @@ public function resolve(
4849
}
4950
/** @var Category $category */
5051
$category = $value['model'];
51-
$blockId = $category->getLandingPage();
52+
$blockId = (int)$category->getLandingPage();
53+
$storeId = (int)$context->getExtensionAttributes()->getStore()->getId();
5254

5355
if (empty($blockId)) {
5456
return null;
5557
}
5658

5759
try {
58-
$block = $this->blockProvider->getData($blockId);
60+
$blockData = $this->blockProvider->getBlockById($blockId, $storeId);
5961
} catch (NoSuchEntityException $e) {
60-
return null;
62+
return new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
6163
}
6264

63-
return $block;
65+
return $blockData;
6466
}
6567
}

app/code/Magento/CmsGraphQl/Model/Resolver/Blocks.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1515
use Magento\Framework\GraphQl\Query\ResolverInterface;
1616
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17+
use function is_numeric;
1718

1819
/**
1920
* CMS blocks field resolver, used for GraphQL request processing
@@ -44,14 +45,13 @@ public function resolve(
4445
array $value = null,
4546
array $args = null
4647
) {
47-
48+
$storeId = (int)$context->getExtensionAttributes()->getStore()->getId();
4849
$blockIdentifiers = $this->getBlockIdentifiers($args);
49-
$blocksData = $this->getBlocksData($blockIdentifiers);
50+
$blocksData = $this->getBlocksData($blockIdentifiers, $storeId);
5051

51-
$resultData = [
52+
return [
5253
'items' => $blocksData,
5354
];
54-
return $resultData;
5555
}
5656

5757
/**
@@ -74,15 +74,22 @@ private function getBlockIdentifiers(array $args): array
7474
* Get blocks data
7575
*
7676
* @param array $blockIdentifiers
77+
* @param int $storeId
7778
* @return array
7879
* @throws GraphQlNoSuchEntityException
7980
*/
80-
private function getBlocksData(array $blockIdentifiers): array
81+
private function getBlocksData(array $blockIdentifiers, int $storeId): array
8182
{
8283
$blocksData = [];
8384
foreach ($blockIdentifiers as $blockIdentifier) {
8485
try {
85-
$blocksData[$blockIdentifier] = $this->blockDataProvider->getData($blockIdentifier);
86+
if (!is_numeric($blockIdentifier)) {
87+
$blocksData[$blockIdentifier] = $this->blockDataProvider
88+
->getBlockByIdentifier($blockIdentifier, $storeId);
89+
} else {
90+
$blocksData[$blockIdentifier] = $this->blockDataProvider
91+
->getBlockById((int)$blockIdentifier, $storeId);
92+
}
8693
} catch (NoSuchEntityException $e) {
8794
$blocksData[$blockIdentifier] = new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
8895
}

app/code/Magento/CmsGraphQl/Model/Resolver/DataProvider/Block.php

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
use Magento\Cms\Api\BlockRepositoryInterface;
1111
use Magento\Cms\Api\Data\BlockInterface;
12+
use Magento\Framework\Api\SearchCriteriaBuilder;
1213
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Store\Model\Store;
1315
use Magento\Widget\Model\Template\FilterEmulate;
1416

1517
/**
@@ -27,43 +29,87 @@ class Block
2729
*/
2830
private $widgetFilter;
2931

32+
/**
33+
* @var SearchCriteriaBuilder
34+
*/
35+
private $searchCriteriaBuilder;
36+
3037
/**
3138
* @param BlockRepositoryInterface $blockRepository
3239
* @param FilterEmulate $widgetFilter
40+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
3341
*/
3442
public function __construct(
3543
BlockRepositoryInterface $blockRepository,
36-
FilterEmulate $widgetFilter
44+
FilterEmulate $widgetFilter,
45+
SearchCriteriaBuilder $searchCriteriaBuilder
3746
) {
3847
$this->blockRepository = $blockRepository;
3948
$this->widgetFilter = $widgetFilter;
49+
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
4050
}
4151

4252
/**
43-
* Get block data
53+
* Get block data by identifier
4454
*
4555
* @param string $blockIdentifier
56+
* @param int $storeId
57+
* @return array
58+
* @throws NoSuchEntityException
59+
*/
60+
public function getBlockByIdentifier(string $blockIdentifier, int $storeId): array
61+
{
62+
$blockData = $this->fetchBlockData($blockIdentifier, BlockInterface::IDENTIFIER, $storeId);
63+
64+
return $blockData;
65+
}
66+
67+
/**
68+
* Get block data by block_id
69+
*
70+
* @param int $blockId
71+
* @param int $storeId
4672
* @return array
4773
* @throws NoSuchEntityException
4874
*/
49-
public function getData(string $blockIdentifier): array
75+
public function getBlockById(int $blockId, int $storeId): array
5076
{
51-
$block = $this->blockRepository->getById($blockIdentifier);
77+
$blockData = $this->fetchBlockData($blockId, BlockInterface::BLOCK_ID, $storeId);
5278

53-
if (false === $block->isActive()) {
79+
return $blockData;
80+
}
81+
82+
/**
83+
* Fetch black data by either id or identifier field
84+
*
85+
* @param mixed $identifier
86+
* @param string $field
87+
* @param int $storeId
88+
* @return array
89+
* @throws NoSuchEntityException
90+
*/
91+
private function fetchBlockData($identifier, string $field, int $storeId): array
92+
{
93+
$searchCriteria = $this->searchCriteriaBuilder
94+
->addFilter($field, $identifier)
95+
->addFilter(Store::STORE_ID, [$storeId, Store::DEFAULT_STORE_ID], 'in')
96+
->addFilter(BlockInterface::IS_ACTIVE, true)->create();
97+
98+
$blockResults = $this->blockRepository->getList($searchCriteria)->getItems();
99+
100+
if (empty($blockResults)) {
54101
throw new NoSuchEntityException(
55-
__('The CMS block with the "%1" ID doesn\'t exist.', $blockIdentifier)
102+
__('The CMS block with the "%1" ID doesn\'t exist.', $identifier)
56103
);
57104
}
58105

106+
$block = current($blockResults);
59107
$renderedContent = $this->widgetFilter->filterDirective($block->getContent());
60-
61-
$blockData = [
108+
return [
62109
BlockInterface::BLOCK_ID => $block->getId(),
63110
BlockInterface::IDENTIFIER => $block->getIdentifier(),
64111
BlockInterface::TITLE => $block->getTitle(),
65112
BlockInterface::CONTENT => $renderedContent,
66113
];
67-
return $blockData;
68114
}
69115
}

app/code/Magento/CmsGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"php": "~7.3.0||~7.4.0",
77
"magento/framework": "*",
88
"magento/module-cms": "*",
9-
"magento/module-widget": "*"
9+
"magento/module-widget": "*",
10+
"magento/module-store": "*"
1011
},
1112
"suggest": {
1213
"magento/module-graph-ql": "*",

dev/tests/api-functional/testsuite/Magento/GraphQl/CatalogCms/CategoryBlockTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,29 @@ public function testCategoryCmsBlock()
5959
$this->assertEquals($block->getIdentifier(), $actualBlock['identifier']);
6060
$this->assertEquals($renderedContent, $actualBlock['content']);
6161
}
62+
63+
/**
64+
* @magentoApiDataFixture Magento/Catalog/_files/category_tree.php
65+
*/
66+
public function testCategoryWithNoCmsBlock()
67+
{
68+
$query = <<<QUERY
69+
{
70+
category(id: 401){
71+
name
72+
cms_block{
73+
identifier
74+
title
75+
content
76+
}
77+
}
78+
}
79+
QUERY;
80+
81+
$response = $this->graphQlQuery($query);
82+
$this->assertArrayNotHasKey('errors', $response);
83+
$this->assertNotEmpty($response['category']);
84+
$this->assertArrayHasKey('cms_block', $response['category']);
85+
$this->assertEquals(null, $response['category']['cms_block']);
86+
}
6287
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Cms/CmsBlockTest.php

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\GraphQl\Cms;
99

1010
use Magento\Cms\Api\BlockRepositoryInterface;
11+
use Magento\Store\Model\Store;
1112
use Magento\TestFramework\Helper\Bootstrap;
1213
use Magento\TestFramework\TestCase\GraphQl\ResponseContainsErrorsException;
1314
use Magento\TestFramework\TestCase\GraphQlAbstract;
@@ -206,4 +207,130 @@ public function testGetEnabledAndDisabledCmsBlockInOneRequest()
206207
$responseData['errors'][0]['message']
207208
);
208209
}
210+
211+
/**
212+
* Verify correct CMS block information per store
213+
*
214+
* @magentoApiDataFixture Magento/Store/_files/multiple_websites_with_store_groups_stores.php
215+
* @magentoApiDataFixture Magento/Cms/_files/blocks_for_different_stores.php
216+
*/
217+
public function testGetCmsBlockPerSpecificStore(): void
218+
{
219+
$blockIdentifier1 = 'test-block';
220+
$blockIdentifier2 = 'test-block-2';
221+
$secondStoreCode = 'second_store_view';
222+
$thirdStoreCode = 'third_store_view';
223+
224+
//Verify the correct block information for second store is returned
225+
$cmsBlockResponseSecondStore = $this->getCmsBlockQuery($blockIdentifier1, $secondStoreCode);
226+
self::assertArrayHasKey('cmsBlocks', $cmsBlockResponseSecondStore);
227+
self::assertArrayHasKey('items', $cmsBlockResponseSecondStore['cmsBlocks']);
228+
self::assertEquals('test-block', $cmsBlockResponseSecondStore['cmsBlocks']['items'][0]['identifier']);
229+
self::assertEquals('Second store block', $cmsBlockResponseSecondStore['cmsBlocks']['items'][0]['title']);
230+
self::assertEquals('second_store_view', $cmsBlockResponseSecondStore['storeConfig']['code']);
231+
232+
//Verify the correct block information for third store is returned
233+
$cmsBlockResponseThirdStore = $this->getCmsBlockQuery($blockIdentifier1, $thirdStoreCode);
234+
self::assertArrayHasKey('cmsBlocks', $cmsBlockResponseThirdStore);
235+
self::assertArrayHasKey('items', $cmsBlockResponseThirdStore['cmsBlocks']);
236+
self::assertEquals('test-block', $cmsBlockResponseThirdStore['cmsBlocks']['items'][0]['identifier']);
237+
self::assertEquals('Third store block', $cmsBlockResponseThirdStore['cmsBlocks']['items'][0]['title']);
238+
self::assertEquals('third_store_view', $cmsBlockResponseThirdStore['storeConfig']['code']);
239+
240+
//Verify the correct block information for second block for second store is returned
241+
$cmsBlockResponseSecondStore = $this->getCmsBlockQuery($blockIdentifier2, $secondStoreCode);
242+
self::assertArrayHasKey('cmsBlocks', $cmsBlockResponseSecondStore);
243+
self::assertArrayHasKey('items', $cmsBlockResponseSecondStore['cmsBlocks']);
244+
self::assertEquals('test-block-2', $cmsBlockResponseSecondStore['cmsBlocks']['items'][0]['identifier']);
245+
self::assertEquals('Second store block 2', $cmsBlockResponseSecondStore['cmsBlocks']['items'][0]['title']);
246+
self::assertEquals('second_store_view', $cmsBlockResponseSecondStore['storeConfig']['code']);
247+
248+
//Verify that exception is returned if block is not assigned to the store specified
249+
$this->expectException(\Exception::class);
250+
$this->expectExceptionMessage('The CMS block with the "test-block-2" ID doesn\'t exist');
251+
252+
$query =
253+
<<<QUERY
254+
{
255+
cmsBlocks(identifiers: "$blockIdentifier2") {
256+
items {
257+
identifier
258+
title
259+
content
260+
}
261+
}
262+
}
263+
QUERY;
264+
$headerMap['Store'] = $thirdStoreCode;
265+
$this->graphQlQuery($query, [], '', $headerMap);
266+
}
267+
268+
/**
269+
* Verify CMS block for a disabled store
270+
*
271+
* @magentoApiDataFixture Magento/Store/_files/multiple_websites_with_store_groups_stores.php
272+
* @magentoApiDataFixture Magento/Cms/_files/blocks_for_different_stores.php
273+
*/
274+
public function testGetCmsBlockForDisabledStore(): void
275+
{
276+
$blockIdentifier = 'test-block';
277+
$thirdStoreCode = 'third_store_view';
278+
$store = Bootstrap::getObjectManager()->get(Store::class);
279+
$store->load('third_store_view', 'code')->setIsActive(0)->save();
280+
$this->expectException(\Exception::class);
281+
$this->expectExceptionMessage('Requested store is not found');
282+
$this->getCmsBlockQuery($blockIdentifier, $thirdStoreCode);
283+
}
284+
285+
/**
286+
* @magentoApiDataFixture Magento/Cms/_files/block_default_store.php
287+
*/
288+
public function testGetCmsBlockAssignedToDefaultStore(): void
289+
{
290+
$blockIdentifier = 'default_store_block';
291+
$query = <<<QUERY
292+
{
293+
cmsBlocks(identifiers: "$blockIdentifier") {
294+
items {
295+
identifier
296+
title
297+
content
298+
}
299+
}
300+
}
301+
QUERY;
302+
$response = $this->graphQlQuery($query);
303+
$this->assertArrayNotHasKey('errors', $response);
304+
$this->assertArrayHasKey('cmsBlocks', $response);
305+
$this->assertCount(1, $response['cmsBlocks']['items']);
306+
$this->assertEquals($blockIdentifier, $response['cmsBlocks']['items'][0]['identifier']);
307+
}
308+
309+
/**
310+
* Get cmsBlockQuery per store
311+
*
312+
* @param string $blockIdentifier
313+
* @param string $storeCode
314+
* @return array
315+
* @throws \Exception
316+
*/
317+
private function getCmsBlockQuery($blockIdentifier, $storeCode): array
318+
{
319+
$query =
320+
<<<QUERY
321+
{
322+
cmsBlocks(identifiers: "$blockIdentifier") {
323+
items {
324+
identifier
325+
title
326+
content
327+
}
328+
}
329+
storeConfig{code}
330+
}
331+
QUERY;
332+
$headerMap['Store'] = $storeCode;
333+
$response = $this->graphQlQuery($query, [], '', $headerMap);
334+
return $response;
335+
}
209336
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Cms\Model\Block;
9+
use Magento\Store\Model\Store;
10+
use Magento\TestFramework\Helper\Bootstrap;
11+
12+
/** @var $block Block */
13+
$block = Bootstrap::getObjectManager()->create(Block::class);
14+
$block->setTitle(
15+
'CMS Block Title'
16+
)->setIdentifier(
17+
'default_store_block'
18+
)->setContent(
19+
'<h1>Fixture Block Title</h1>
20+
<a href="{{store url=""}}">store url</a>
21+
<p>Config value: "{{config path="web/unsecure/base_url"}}".</p>
22+
<p>Custom variable: "{{customvar code="variable_code"}}".</p>'
23+
)->setIsActive(
24+
1
25+
)->setStores(
26+
[Store::DEFAULT_STORE_ID]
27+
)->save();

0 commit comments

Comments
 (0)