Skip to content

Commit 447f3e4

Browse files
authored
Merge pull request #3 from ctidigital/blocks
Blocks component now added
2 parents e2bba2a + 7456b49 commit 447f3e4

File tree

12 files changed

+324
-2
lines changed

12 files changed

+324
-2
lines changed

Model/Component/Blocks.php

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
<?php
2+
3+
namespace CtiDigital\Configurator\Model\Component;
4+
5+
use CtiDigital\Configurator\Model\Exception\ComponentException;
6+
use CtiDigital\Configurator\Model\LoggingInterface;
7+
use Magento\Cms\Api\Data\BlockInterfaceFactory;
8+
use Magento\Store\Api\Data\StoreInterface;
9+
use Magento\Store\Model\StoreFactory;
10+
use Magento\Framework\ObjectManagerInterface;
11+
use Symfony\Component\Yaml\Yaml;
12+
13+
class Blocks extends ComponentAbstract
14+
{
15+
16+
protected $alias = 'blocks';
17+
protected $name = 'Blocks';
18+
protected $description = 'Component to create/maintain blocks.';
19+
20+
/**
21+
* @var BlockInterfaceFactory
22+
*/
23+
protected $blockFactory;
24+
25+
/**
26+
* @var \Magento\Store\Model\Store\Interceptor
27+
*/
28+
protected $storeManager;
29+
30+
/**
31+
* @var \Magento\Framework\Api\SearchCriteriaBuilder
32+
*/
33+
protected $searchBuilder;
34+
35+
/**
36+
* Blocks constructor.
37+
* @param LoggingInterface $log
38+
* @param ObjectManagerInterface $objectManager
39+
* @param BlockInterfaceFactory $blockFactory
40+
*/
41+
public function __construct(
42+
LoggingInterface $log,
43+
ObjectManagerInterface $objectManager,
44+
BlockInterfaceFactory $blockFactory
45+
) {
46+
47+
parent::__construct($log, $objectManager);
48+
49+
$this->blockFactory = $blockFactory;
50+
$this->storeManager = $this->objectManager->create(\Magento\Store\Model\Store::class);
51+
52+
}
53+
54+
protected function canParseAndProcess()
55+
{
56+
$path = BP . '/' . $this->source;
57+
if (!file_exists($path)) {
58+
throw new ComponentException(
59+
sprintf("Could not find file in path %s", $path)
60+
);
61+
}
62+
return true;
63+
}
64+
65+
protected function parseData($source = null)
66+
{
67+
68+
try {
69+
if ($source == null) {
70+
throw new ComponentException(
71+
sprintf('The %s component requires to have a file source definition.', $this->alias)
72+
);
73+
}
74+
75+
$parser = new Yaml();
76+
return $parser->parse(file_get_contents($source));
77+
} catch (ComponentException $e) {
78+
$this->log->logError($e->getMessage());
79+
}
80+
}
81+
82+
/**
83+
* @param array $data
84+
*/
85+
protected function processData($data = null)
86+
{
87+
try {
88+
89+
foreach ($data as $identifier => $data) {
90+
$this->processBlock($identifier, $data);
91+
}
92+
93+
} catch (ComponentException $e) {
94+
$this->log->logError($e->getMessage());
95+
}
96+
}
97+
98+
/**
99+
* @param $identifier
100+
* @param $blockData
101+
* @SuppressWarnings(PHPMD)
102+
*/
103+
private function processBlock($identifier, $blockData)
104+
{
105+
try {
106+
107+
// Loop through the block data
108+
foreach ($blockData['block'] as $data) {
109+
110+
$this->log->logComment(sprintf("Checking for existing blocks with identifier '%s'", $identifier));
111+
112+
// Load a collection blocks
113+
$blocks = $this->blockFactory->create()->getCollection()->addFieldToFilter('identifier', $identifier);
114+
115+
// Set initial vars
116+
$canSave = false;
117+
$block = null;
118+
119+
// Check if there are existing blocks
120+
if ($blocks->count()) {
121+
$stores = array();
122+
123+
// Check if stores are specified
124+
if (isset($data['stores'])) {
125+
$stores = $data['stores'];
126+
}
127+
128+
// Find the exact block to process
129+
$block = $this->getBlockToProcess($identifier, $blocks, $stores);
130+
}
131+
132+
// If there is still no block to play with, create a new block object.
133+
if (is_null($block)) {
134+
$block = $this->blockFactory->create();
135+
$block->setIdentifier($identifier);
136+
$canSave = true;
137+
}
138+
139+
// Loop through each attribute of the data array
140+
foreach ($data as $key => $value) {
141+
142+
// Check if content is from a file source
143+
if ($key == "source") {
144+
$key = 'content';
145+
$value = file_get_contents(BP . '/' . $value);
146+
}
147+
148+
// Skip stores
149+
if ($key == "stores") {
150+
continue;
151+
}
152+
153+
// Log the old value if any
154+
$this->log->logComment(sprintf(
155+
"Checking block %s, key %s => %s",
156+
$identifier . ' (' . $block->getId() . ')',
157+
$key,
158+
$block->getData($key)
159+
), 1);
160+
161+
// Check if there is a difference in value
162+
if ($block->getData($key) != $value) {
163+
164+
// If there is, allow the block to be saved
165+
$canSave = true;
166+
$block->setData($key, $value);
167+
168+
$this->log->logInfo(sprintf(
169+
"Set block %s, key %s => %s",
170+
$identifier . ' (' . $block->getId() . ')',
171+
$key,
172+
$value
173+
), 1);
174+
}
175+
}
176+
177+
// Process stores
178+
// @todo compare stores to see if a save is required
179+
$block->setStoreId(0);
180+
if (isset($data['stores'])) {
181+
$block->unsetData('store_id');
182+
$block->unsetData('store_data');
183+
$stores = array();
184+
foreach ($data['stores'] as $code) {
185+
$stores[] = $this->getStoreByCode($code)->getId();
186+
}
187+
$block->setStores($stores);
188+
}
189+
190+
// If we can save the block
191+
if ($canSave) {
192+
$block->save();
193+
$this->log->logInfo(sprintf(
194+
"Save block %s",
195+
$identifier . ' (' . $block->getId() . ')'
196+
));
197+
}
198+
199+
}
200+
} catch (ComponentException $e) {
201+
$this->log->logError($e->getMessage());
202+
}
203+
}
204+
205+
206+
/**
207+
* Find the block to process given the identifier, block collection and optionally stores
208+
*
209+
* @param String $identifier
210+
* @param \Magento\Cms\Model\ResourceModel\Block\Collection $blocks
211+
* @param array $stores
212+
* @return \Magento\Cms\Model\Block|null
213+
*/
214+
private function getBlockToProcess(
215+
$identifier,
216+
\Magento\Cms\Model\ResourceModel\Block\Collection $blocks,
217+
$stores = array()
218+
) {
219+
220+
// If there is only 1 block and stores hasn't been specified
221+
if ($blocks->count() == 1 && count($stores) == 0) {
222+
223+
// Return that one block
224+
return $blocks->getFirstItem();
225+
}
226+
227+
// If we do have stores specified
228+
if (count($stores) > 0) {
229+
230+
// Use first store as filter to get the block ID.
231+
// Ideally, we would want to do something more intelligent here.
232+
$store = $this->getStoreByCode($stores[0]);
233+
$blocks = $this->blockFactory->create()->getCollection()
234+
->addStoreFilter($store, false)
235+
->addFieldToFilter('identifier', $identifier);
236+
237+
// We should have no more than 1 block unless something funky is happening. Return the first block anyway.
238+
if ($blocks->count() >= 1) {
239+
return $blocks->getFirstItem();
240+
}
241+
}
242+
243+
// In all other scenarios, return null as we can't find the block.
244+
return null;
245+
}
246+
247+
/**
248+
* @param String $code
249+
* @return \Magento\Store\Model\Store
250+
*/
251+
private function getStoreByCode($code)
252+
{
253+
254+
// Load the store object
255+
$store = $this->storeManager->load($code, 'code');
256+
257+
// Check if we get back a store ID.
258+
if (!$store->getId()) {
259+
260+
// If not, stop the process by throwing an exception
261+
throw new ComponentException(sprintf("No store with code '%s' found", $code));
262+
}
263+
264+
return $store;
265+
}
266+
}

Model/Processor.php

+6
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ private function runIndividualComponents()
116116
foreach ($this->components as $componentAlias) {
117117

118118
// Get the config for the component from the master yaml array
119+
if (!isset($master[$componentAlias])) {
120+
throw new ComponentException(
121+
sprintf("No master yaml definition with the alias '%s' found", $componentAlias)
122+
);
123+
}
124+
119125
$masterConfig = $master[$componentAlias];
120126

121127
// Run that component

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ php vendor/bin/phpunit --coverage-clover build/logs/clover.xml vendor/ctidigital
4141
|---------------------------|--------------------|---------------|--------------------|
4242
| Websites | :white_check_mark: | :x: | :white_check_mark: |
4343
| System Configuration | :white_check_mark: | :x: | :white_check_mark: |
44+
| Blocks | :white_check_mark: | :x: | :white_check_mark: |
4445
| Attribute Sets | :x: | :x: | :x: |
4546
| Attributes | :x: | :x: | :x: |
4647
| Categories | :x: | :x: | :x: |
4748
| Products | :x: | :x: | :x: |
4849
| Admin Roles | :x: | :x: | :x: |
4950
| Admin Users | :x: | :x: | :x: |
5051
| Pages | :x: | :x: | :x: |
51-
| Static Blocks | :x: | :x: | :x: |
5252
| Customers | :x: | :x: | :x: |
5353
| Media | :x: | :x: | :x: |
5454
| Widgets | :x: | :x: | :x: |
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>This block belongs to all stores.</h1>

Samples/Components/Blocks/blocks.yaml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
all_stores_identifier:
2+
block:
3+
-
4+
source: ../configurator/Blocks/allstores.html
5+
title: All stores
6+
is_active: 1
7+
certain_stores_identifier:
8+
block:
9+
-
10+
source: ../configurator/Blocks/uk.html
11+
title: UK Block
12+
is_active: 1
13+
stores:
14+
- default
15+
-
16+
source: ../configurator/Blocks/us.html
17+
title: US Block
18+
is_active: 1
19+
stores:
20+
- usa_en_us

Samples/Components/Blocks/uk.html

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>UK Block</h1>

Samples/Components/Blocks/us.html

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>US Block</h1>

Samples/master.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ products:
3333
sources:
3434
- ../configurator/Products/simple.csv
3535
- ../configurator/Products/configurable.csv
36+
env:
37+
local:
38+
mode: maintain
39+
log: debug
40+
blocks:
41+
enabled: 1
42+
method: code
43+
sources:
44+
- ../configurator/Blocks/blocks.yaml
3645
env:
3746
local:
3847
mode: maintain

Test/Unit/Component/BlocksTest.php

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace CtiDigital\Configurator\Test\Unit\Component;
4+
5+
use CtiDigital\Configurator\Model\Component\Blocks;
6+
use Magento\Cms\Api\Data\BlockInterfaceFactory;
7+
8+
class BlocksTest extends ComponentAbstractTestCase
9+
{
10+
11+
protected function componentSetUp()
12+
{
13+
$blockInterface = $this->getMock(BlockInterfaceFactory::class);
14+
$this->component = new Blocks($this->logInterface, $this->objectManager, $blockInterface);
15+
$this->className = Blocks::class;
16+
}
17+
}

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"satooshi/php-coveralls": "^1.0",
2222
"magento/mtf": "dev-develop"
2323
},
24-
"version": "0.3.1-dev",
24+
"version": "0.4.0-dev",
2525
"autoload": {
2626
"files": [ "registration.php" ],
2727
"psr-4": {

etc/configurator.xml

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
<component name="config" class="CtiDigital\Configurator\Model\Component\Config" />
77
<component name="categories" class="CtiDigital\Configurator\Model\Component\Categories" />
88
<component name="products" class="CtiDigital\Configurator\Model\Component\Products" />
9+
<component name="blocks" class="CtiDigital\Configurator\Model\Component\Blocks" />
910
</config>

0 commit comments

Comments
 (0)