Skip to content

Commit 98a1c33

Browse files
tools-utrecht-hhDylan Maurits
authored andcommitted
Merge pull request #27 from experius/feature/import_from_csv
[FEATURE][BACI-448] implemented csv import from backend
2 parents df821d0 + fb15086 commit 98a1c33

5 files changed

Lines changed: 366 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,67 @@
1-
## 1.4.3 (2024-05-31)
1+
## 1.7.0 (2025-09-24)
2+
3+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.7.0)
4+
5+
* [FEATURE][BACI-448] implemented csv import from backend *(Dylan Maurits)*
6+
7+
8+
## 1.6.1 (2025-09-22)
9+
10+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.6.1)
11+
12+
* Modify getExcludeList to return an array *(Simon Vianen)*
13+
14+
15+
## 1.6.0 (2025-09-19)
16+
17+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.6.0)
18+
19+
* [FEATURE][IN23-453] Add configurable exclude list to be able to exclude url's from the logging *(Simon Vianen)*
20+
* [FEATURE][IN23-453]Move settings to settings helper *(Simon Vianen)*
21+
22+
23+
## 1.5.2 (2025-08-21)
24+
25+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.5.2)
26+
27+
* [BUGFIX][NUA-149]update to use explicit nullable type *(Simon Vianen)*
28+
29+
30+
## 1.5.1 (2024-11-18)
31+
32+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.5.1)
33+
34+
* put '!==' next to stringpos because it didn't satisfy coding standards *(Simon Vianen)*
35+
36+
37+
## 1.5.0 (2024-10-25)
38+
39+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.5.0)
40+
41+
* Added MANUAL.md *(pascalexperius)*
42+
* Update README.md *(Matthieu)*
43+
* Update README.md *(Matthieu)*
44+
* added function to get store code from url *(Simon Vianen)*
45+
* [FEATURE][IN23-284]changed str_strt with strpos for php 7 compatibility *(Simon Vianen)*
46+
47+
48+
## 1.4.4 (2024-07-08)
49+
50+
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.4.4)
51+
52+
* [BUGFIX] fixed issue where a var_dump breaks the grapql return *(thokiller)*
53+
54+
55+
## 1.4.3 (2024-06-04)
256

357
[View Release](git@github.com:experius/Magento-2-Module-PageNotFound.git/commits/tag/1.4.3)
458

559
* [FEATURE][JIRA-123]added graphQL suport in base function to extend pagenotfoundgraphql *(simon vianen)*
660
* [FEATURE][JIRA-123]git added docblock, fixt typo, changed from url creation for graphql to the top of the savePageNotFound Function *(simon vianen)*
761
* [FEATURE][JIRA-123]Added my name to the composer.json *(simon vianen)*
62+
* [FEATURE][JIRA-123]removed unused code *(simon vianen)*
63+
* [DOCS] Updated the CHANGELOG.md *(simon vianen)*
64+
* [FEATURE][JIRA-123]codescan update *(simon vianen)*
865

966

1067
## 1.4.2 (2024-03-26)

Model/Import/Redirects.php

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
<?php
2+
namespace Experius\PageNotFound\Model\Import;
3+
4+
use Exception;
5+
use Magento\Framework\App\ResourceConnection;
6+
use Magento\Framework\DB\Adapter\AdapterInterface;
7+
use Magento\Framework\Json\Helper\Data as JsonHelper;
8+
use Magento\ImportExport\Helper\Data as ImportHelper;
9+
use Magento\ImportExport\Model\Import;
10+
use Magento\ImportExport\Model\Import\Entity\AbstractEntity;
11+
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
12+
use Magento\ImportExport\Model\ResourceModel\Helper;
13+
use Magento\ImportExport\Model\ResourceModel\Import\Data;
14+
15+
/**
16+
* Class Courses
17+
*/
18+
class Redirects extends AbstractEntity
19+
{
20+
const ENTITY_CODE = 'pagenotfound';
21+
const TABLE = 'experius_page_not_found';
22+
const ENTITY_ID_COLUMN = 'page_not_found_id';
23+
24+
/**
25+
* If we should check column names
26+
*/
27+
protected $needColumnCheck = true;
28+
29+
/**
30+
* Need to log in import history
31+
*/
32+
protected $logInHistory = true;
33+
34+
/**
35+
* Permanent entity columns.
36+
*/
37+
protected $_permanentAttributes = [
38+
'page_not_found_id'
39+
];
40+
41+
/**
42+
* Valid column names
43+
*/
44+
protected $validColumnNames = [
45+
'page_not_found_id',
46+
'from_url',
47+
'to_url'
48+
];
49+
50+
/**
51+
* @var AdapterInterface
52+
*/
53+
protected $connection;
54+
55+
/**
56+
* @var ResourceConnection
57+
*/
58+
private $resource;
59+
60+
/**
61+
* Courses constructor.
62+
*
63+
* @param JsonHelper $jsonHelper
64+
* @param ImportHelper $importExportData
65+
* @param Data $importData
66+
* @param ResourceConnection $resource
67+
* @param Helper $resourceHelper
68+
* @param ProcessingErrorAggregatorInterface $errorAggregator
69+
*/
70+
public function __construct(
71+
JsonHelper $jsonHelper,
72+
ImportHelper $importExportData,
73+
Data $importData,
74+
ResourceConnection $resource,
75+
Helper $resourceHelper,
76+
ProcessingErrorAggregatorInterface $errorAggregator
77+
) {
78+
$this->jsonHelper = $jsonHelper;
79+
$this->_importExportData = $importExportData;
80+
$this->_resourceHelper = $resourceHelper;
81+
$this->_dataSourceModel = $importData;
82+
$this->resource = $resource;
83+
$this->connection = $resource->getConnection(ResourceConnection::DEFAULT_CONNECTION);
84+
$this->errorAggregator = $errorAggregator;
85+
}
86+
87+
/**
88+
* Entity type code getter.
89+
*
90+
* @return string
91+
*/
92+
public function getEntityTypeCode()
93+
{
94+
return static::ENTITY_CODE;
95+
}
96+
97+
/**
98+
* Get available columns
99+
*
100+
* @return array
101+
*/
102+
public function getValidColumnNames(): array
103+
{
104+
return $this->validColumnNames;
105+
}
106+
107+
/**
108+
* Row validation
109+
*
110+
* @param array $rowData
111+
* @param int $rowNum
112+
*
113+
* @return bool
114+
*/
115+
public function validateRow(array $rowData, $rowNum): bool
116+
{
117+
if (isset($this->_validatedRows[$rowNum])) {
118+
return !$this->getErrorAggregator()->isRowInvalid($rowNum);
119+
}
120+
121+
$this->_validatedRows[$rowNum] = true;
122+
123+
return !$this->getErrorAggregator()->isRowInvalid($rowNum);
124+
}
125+
126+
/**
127+
* Import data
128+
*
129+
* @return bool
130+
*
131+
* @throws Exception
132+
*/
133+
protected function _importData(): bool
134+
{
135+
switch ($this->getBehavior()) {
136+
case Import::BEHAVIOR_DELETE:
137+
$this->deleteEntity();
138+
break;
139+
case Import::BEHAVIOR_REPLACE:
140+
$this->saveAndReplaceEntity();
141+
break;
142+
case Import::BEHAVIOR_APPEND:
143+
$this->saveAndReplaceEntity();
144+
break;
145+
}
146+
147+
return true;
148+
}
149+
150+
/**
151+
* Delete entities
152+
*
153+
* @return bool
154+
*/
155+
private function deleteEntity(): bool
156+
{
157+
$rows = [];
158+
while ($bunch = $this->_dataSourceModel->getNextBunch()) {
159+
foreach ($bunch as $rowNum => $rowData) {
160+
$this->validateRow($rowData, $rowNum);
161+
162+
if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) {
163+
$rowId = $rowData[static::ENTITY_ID_COLUMN];
164+
$rows[] = $rowId;
165+
}
166+
167+
if ($this->getErrorAggregator()->hasToBeTerminated()) {
168+
$this->getErrorAggregator()->addRowToSkip($rowNum);
169+
}
170+
}
171+
}
172+
173+
if ($rows) {
174+
return $this->deleteEntityFinish(array_unique($rows));
175+
}
176+
177+
return false;
178+
}
179+
180+
/**
181+
* Save and replace entities
182+
*
183+
* @return void
184+
*/
185+
private function saveAndReplaceEntity()
186+
{
187+
$behavior = $this->getBehavior();
188+
$rows = [];
189+
while ($bunch = $this->_dataSourceModel->getNextBunch()) {
190+
$entityList = [];
191+
192+
foreach ($bunch as $rowNum => $row) {
193+
if (!$this->validateRow($row, $rowNum)) {
194+
continue;
195+
}
196+
197+
if ($this->getErrorAggregator()->hasToBeTerminated()) {
198+
$this->getErrorAggregator()->addRowToSkip($rowNum);
199+
200+
continue;
201+
}
202+
203+
$rowId = $row[static::ENTITY_ID_COLUMN];
204+
$rows[] = $rowId;
205+
$columnValues = [];
206+
207+
foreach ($this->getAvailableColumns() as $columnKey) {
208+
$columnValues[$columnKey] = $row[$columnKey];
209+
}
210+
211+
$entityList[$rowId][] = $columnValues;
212+
$this->countItemsCreated += (int) !isset($row[static::ENTITY_ID_COLUMN]);
213+
$this->countItemsUpdated += (int) isset($row[static::ENTITY_ID_COLUMN]);
214+
}
215+
216+
if (Import::BEHAVIOR_REPLACE === $behavior) {
217+
if ($rows && $this->deleteEntityFinish(array_unique($rows))) {
218+
$this->saveEntityFinish($entityList);
219+
}
220+
} elseif (Import::BEHAVIOR_APPEND === $behavior) {
221+
$this->saveEntityFinish($entityList);
222+
}
223+
}
224+
}
225+
226+
/**
227+
* Save entities
228+
*
229+
* @param array $entityData
230+
*
231+
* @return bool
232+
*/
233+
private function saveEntityFinish(array $entityData): bool
234+
{
235+
if ($entityData) {
236+
$tableName = $this->connection->getTableName(static::TABLE);
237+
$rows = [];
238+
239+
foreach ($entityData as $entityRows) {
240+
foreach ($entityRows as $row) {
241+
$rows[] = $row;
242+
}
243+
}
244+
245+
if ($rows) {
246+
$this->connection->insertOnDuplicate($tableName, $rows, $this->getAvailableColumns());
247+
248+
return true;
249+
}
250+
251+
return false;
252+
}
253+
}
254+
255+
/**
256+
* Delete entities
257+
*
258+
* @param array $entityIds
259+
*
260+
* @return bool
261+
*/
262+
private function deleteEntityFinish(array $entityIds): bool
263+
{
264+
if ($entityIds) {
265+
try {
266+
$this->countItemsDeleted += $this->connection->delete(
267+
$this->connection->getTableName(static::TABLE),
268+
$this->connection->quoteInto(static::ENTITY_ID_COLUMN . ' IN (?)', $entityIds)
269+
);
270+
271+
return true;
272+
} catch (Exception $e) {
273+
return false;
274+
}
275+
}
276+
277+
return false;
278+
}
279+
280+
/**
281+
* Get available columns
282+
*
283+
* @return array
284+
*/
285+
private function getAvailableColumns(): array
286+
{
287+
return $this->validColumnNames;
288+
}
289+
}

0 commit comments

Comments
 (0)