Completed
Push — master ( 3ca74c...81f65b )
by Fabian
11s
created

ProductBuilder::withCategoryIds()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace TddWizard\Fixtures\Catalog;
4
5
use Magento\Catalog\Api\Data\ProductInterface;
6
use Magento\Catalog\Api\Data\ProductWebsiteLinkInterface;
7
use Magento\Catalog\Api\Data\ProductWebsiteLinkInterfaceFactory;
8
use Magento\Catalog\Api\ProductRepositoryInterface;
9
use Magento\Catalog\Api\ProductWebsiteLinkRepositoryInterface;
10
use Magento\Catalog\Model\Product;
11
use Magento\Catalog\Model\Product\Attribute\Source\Status;
12
use Magento\Catalog\Model\Product\Visibility;
13
use Magento\CatalogInventory\Api\Data\StockItemInterface;
14
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
15
use Magento\Framework\ObjectManagerInterface;
16
use Magento\Indexer\Model\IndexerFactory;
17
18
/**
19
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
20
 * @SuppressWarnings(PHPMD.UnusedPrivateField)
21
 */
22
class ProductBuilder
23
{
24
    /**
25
     * @var ProductInterface
26
     */
27
    protected $product;
28
    /**
29
     * @var ProductRepositoryInterface
30
     */
31
    private $productRepository;
32
    /**
33
     * @var mixed[][]
34
     */
35
    private $storeSpecificValues = [];
36
    /**
37
     * @var int[]
38
     */
39
    private $websiteIds = [];
40
    /**
41
     * @var int[]
42
     */
43
    private $categoryIds = [];
44
    /**
45
     * @var ProductWebsiteLinkRepositoryInterface
46
     */
47
    private $websiteLinkRepository;
48
    /**
49
     * @var StockItemRepositoryInterface
50
     */
51
    private $stockItemRepository;
52
    /**
53
     * @var ProductWebsiteLinkInterfaceFactory
54
     */
55
    private $websiteLinkFactory;
56
    /**
57
     * @var IndexerFactory
58
     */
59
    private $indexerFactory;
60
61
    public function __construct(
62
        ProductRepositoryInterface $productRepository,
63
        StockItemRepositoryInterface $stockItemRepository,
64
        ProductWebsiteLinkRepositoryInterface $websiteLinkRepository,
65
        ProductWebsiteLinkInterfaceFactory $websiteLinkFactory,
66
        IndexerFactory $indexerFactory,
67
        ProductInterface $product,
68
        array $websiteIds,
69
        array $storeSpecificValues
70
    ) {
71
        $this->productRepository = $productRepository;
72
        $this->websiteLinkRepository = $websiteLinkRepository;
73
        $this->stockItemRepository = $stockItemRepository;
74
        $this->websiteLinkFactory = $websiteLinkFactory;
75
        $this->indexerFactory = $indexerFactory;
76
        $this->product = $product;
77
        $this->websiteIds = $websiteIds;
78
        $this->storeSpecificValues = $storeSpecificValues;
79
    }
80
81
    public function __clone()
82
    {
83
        $this->product = clone $this->product;
84
    }
85
86
    public static function aSimpleProduct(ObjectManagerInterface $objectManager = null) : ProductBuilder
87
    {
88
        if ($objectManager === null) {
89
            $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
0 ignored issues
show
Bug introduced by
The type Magento\TestFramework\Helper\Bootstrap was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
90
        }
91
        /** @var ProductInterface $product */
92
        $product = $objectManager->create(ProductInterface::class);
93
94
        $product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
95
            ->setAttributeSetId(4)
96
            ->setName('Simple Product')
97
            ->setPrice(10)
98
            ->setVisibility(Visibility::VISIBILITY_BOTH)
99
            ->setStatus(Status::STATUS_ENABLED);
100
        $product->addData([
101
            'tax_class_id' => 1,
102
            'description' => 'Description',
103
        ]);
104
        /** @var StockItemInterface $stockItem */
105
        $stockItem = $objectManager->create(StockItemInterface::class);
106
        $stockItem->setManageStock(true)
107
            ->setQty(100)
108
            ->setIsQtyDecimal(false)
109
            ->setIsInStock(true);
110
        $product->setExtensionAttributes(
111
            $product->getExtensionAttributes()->setStockItem($stockItem)
112
        );
113
114
        return new static(
115
            $objectManager->create(ProductRepositoryInterface::class),
116
            $objectManager->create(StockItemRepositoryInterface::class),
117
            $objectManager->create(ProductWebsiteLinkRepositoryInterface::class),
118
            $objectManager->create(ProductWebsiteLinkInterfaceFactory::class),
119
            $objectManager->create(IndexerFactory::class),
120
            $product,
121
            [1],
122
            []
123
        );
124
    }
125
126
    public function withData(array $data) : ProductBuilder
127
    {
128
        $builder = clone $this;
129
130
        $builder->product->addData($data);
131
132
        return $builder;
133
    }
134
135
    public function withSku(string $sku) : ProductBuilder
136
    {
137
        $builder = clone $this;
138
        $builder->product->setSku($sku);
139
        return $builder;
140
    }
141
142
    public function withName(string $name, $storeId = null) : ProductBuilder
143
    {
144
        $builder = clone $this;
145
        if ($storeId) {
146
            $builder->storeSpecificValues[$storeId][ProductInterface::NAME] = $name;
147
        } else {
148
            $builder->product->setName($name);
149
        }
150
        return $builder;
151
    }
152
153
    /**
154
     * @param int $status
155
     * @param int|null $storeId Pass store ID to set value for specific store.
156
     *                          Attention: Status is configured per website, will affect all stores of the same website
157
     * @return ProductBuilder
158
     */
159
    public function withStatus(int $status, $storeId = null) : ProductBuilder
160
    {
161
        $builder = clone $this;
162
        if ($storeId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $storeId of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
163
            $builder->storeSpecificValues[$storeId][ProductInterface::STATUS] = $status;
164
        } else {
165
            $builder->product->setStatus($status);
166
        }
167
        return $builder;
168
    }
169
170
    public function withVisibility(int $visibility, $storeId = null) : ProductBuilder
171
    {
172
        $builder = clone $this;
173
        if ($storeId) {
174
            $builder->storeSpecificValues[$storeId][ProductInterface::VISIBILITY] = $visibility;
175
        } else {
176
            $builder->product->setVisibility($visibility);
177
        }
178
        return $builder;
179
    }
180
181
    public function withWebsiteIds(array $websiteIds) : ProductBuilder
182
    {
183
        $builder = clone $this;
184
        $builder->websiteIds = $websiteIds;
185
        return $builder;
186
    }
187
188
    public function withCategoryIds(array $categoryIds) : ProductBuilder
189
    {
190
        $builder = clone $this;
191
        $builder->categoryIds = $categoryIds;
192
        return $builder;
193
    }
194
195
    public function withPrice(float $price) : ProductBuilder
196
    {
197
        $builder = clone $this;
198
        $builder->product->setPrice($price);
199
        return $builder;
200
    }
201
202
    public function withTaxClassId($taxClassId) : ProductBuilder
203
    {
204
        $builder = clone $this;
205
        $builder->product->setData('tax_class_id', $taxClassId);
206
        return $builder;
207
    }
208
209
    public function withIsInStock(bool $inStock) : ProductBuilder
210
    {
211
        $builder = clone $this;
212
        $builder->product->getExtensionAttributes()->getStockItem()->setIsInStock($inStock);
213
        return $builder;
214
    }
215
216
    public function withStockQty($qty) : ProductBuilder
217
    {
218
        $builder = clone $this;
219
        $builder->product->getExtensionAttributes()->getStockItem()->setQty($qty);
220
        return $builder;
221
    }
222
223
    public function withWeight($weight) : ProductBuilder
224
    {
225
        $builder = clone $this;
226
        $builder->product->setWeight($weight);
227
        return $builder;
228
    }
229
230
    public function withCustomAttributes(array $values, $storeId = null) : ProductBuilder
231
    {
232
        $builder = clone $this;
233
        foreach ($values as $code => $value) {
234
            if ($storeId) {
235
                $builder->storeSpecificValues[$storeId][$code] = $value;
236
            } else {
237
                $builder->product->setCustomAttribute($code, $value);
238
            }
239
        }
240
        return $builder;
241
    }
242
243
    public function build() : ProductInterface
244
    {
245
        FulltextIndex::ensureTablesAreCreated();
246
        $builder = clone $this;
247
        if (!$builder->product->getSku()) {
248
            $builder->product->setSku(sha1(uniqid('', true)));
249
        }
250
        $builder->product->setCustomAttribute('url_key', $builder->product->getSku());
251
        $builder->product->setCategoryIds($builder->categoryIds);
252
        $product = $builder->productRepository->save($builder->product);
253
        foreach ($builder->websiteIds as $websiteId) {
254
            /** @var ProductWebsiteLinkInterface $websiteLink */
255
            $websiteLink = $builder->websiteLinkFactory->create();
256
            $websiteLink->setWebsiteId($websiteId)->setSku($product->getSku());
257
            $builder->websiteLinkRepository->save($websiteLink);
258
        }
259
        foreach ($builder->storeSpecificValues as $storeId => $values) {
260
            /** @var Product $storeProduct */
261
            $storeProduct = clone $product;
262
            $storeProduct->setStoreId($storeId);
263
            $storeProduct->addData($values);
264
            $storeProduct->save();
0 ignored issues
show
Deprecated Code introduced by
The function Magento\Framework\Model\AbstractModel::save() has been deprecated: 100.1.0 because entities must not be responsible for their own persistence. Service contracts should persist entities. Use resource model "save" to implement service contract persistence operations. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

264
            /** @scrutinizer ignore-deprecated */ $storeProduct->save();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
265
        }
266
        $this->indexerFactory->create()->load('cataloginventory_stock')->reindexRow($product->getId());
267
        return $product;
268
    }
269
}
270