Skip to content

Commit d552184

Browse files
committed
added imports page
1 parent ec74fc1 commit d552184

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

app/base/tools/Utils/Globals.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,13 @@ public function getTokenUserDataClaim(): mixed
661661

662662
/**
663663
* gets csv string from array
664+
*
665+
* @param array $data
666+
* @param array $header
667+
* @param string $delimiter
668+
* @param string $enclosure
669+
* @param string $escape_char
670+
* @return string|false
664671
*/
665672
public function array2csv($data, $header = [], $delimiter = ',', $enclosure = '"', $escape_char = "\\") : string|false
666673
{
@@ -674,4 +681,29 @@ public function array2csv($data, $header = [], $delimiter = ',', $enclosure = '"
674681
rewind($f);
675682
return stream_get_contents($f);
676683
}
684+
685+
/**
686+
* gets csv contents as array
687+
*
688+
* @param string $csvFile
689+
* @return array
690+
*/
691+
public function csv2array(string $csvFile) : array
692+
{
693+
$out = [];
694+
$csvHeader = null;
695+
if (($handle = fopen($csvFile, "r")) !== FALSE) {
696+
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
697+
if ($csvHeader == null) {
698+
$csvHeader = $data;
699+
} else {
700+
$out[] = array_combine($csvHeader, $data);
701+
}
702+
}
703+
704+
fclose($handle);
705+
}
706+
707+
return $out;
708+
}
677709
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.0
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
namespace App\Site\Controllers\Admin;
15+
16+
use Degami\Basics\Exceptions\BasicException;
17+
use App\Base\Abstracts\Controllers\AdminFormPage;
18+
use Degami\PHPFormsApi as FAPI;
19+
use DI\DependencyException;
20+
use DI\NotFoundException;
21+
use Phpfastcache\Exceptions\PhpfastcacheSimpleCacheException;
22+
use HaydenPierce\ClassFinder\ClassFinder;
23+
use Symfony\Component\HttpFoundation\Response;
24+
use App\Base\Abstracts\Models\BaseCollection;
25+
use App\Base\Abstracts\Models\BaseModel;
26+
use App\App;
27+
28+
/**
29+
* "Imports" Admin Page
30+
*/
31+
class Imports extends AdminFormPage
32+
{
33+
/**
34+
* {@inheritdocs}
35+
*
36+
* @return string
37+
*/
38+
protected function getTemplateName(): string
39+
{
40+
return 'form_admin_page';
41+
}
42+
43+
/**
44+
* {@inheritdocs}
45+
*
46+
* @return string
47+
*/
48+
protected function getAccessPermission(): string
49+
{
50+
return 'administer_configuration';
51+
}
52+
53+
/**
54+
* {@inheritdocs}
55+
*
56+
* @return array|null
57+
*/
58+
public Function getAdminPageLink() : array|null
59+
{
60+
return [
61+
'permission_name' => $this->getAccessPermission(),
62+
'route_name' => static::getPageRouteName(),
63+
'icon' => 'archive',
64+
'text' => 'Imports',
65+
'section' => 'system',
66+
];
67+
}
68+
69+
/**
70+
* {@inheritdocs}
71+
*
72+
* @param FAPI\Form $form
73+
* @param array &$form_state
74+
* @return FAPI\Form
75+
* @throws BasicException
76+
* @throws PhpfastcacheSimpleCacheException
77+
* @throws DependencyException
78+
* @throws NotFoundException
79+
*/
80+
public function getFormDefinition(FAPI\Form $form, &$form_state): FAPI\Form
81+
{
82+
$exportableClasses = [];
83+
$modelClasses = ClassFinder::getClassesInNamespace('App\Site\Models');
84+
foreach ($modelClasses as $modelClass) {
85+
if (is_callable([$modelClass, 'isExportable']) && $this->containerCall([$modelClass, 'isExportable']) == true) {
86+
$className = str_replace("App\\Site\\Models\\", "", $modelClass);
87+
$exportableClasses[$modelClass] = $className;
88+
}
89+
}
90+
91+
$form->addField('action', [
92+
'type' => 'value',
93+
'value' => 'import',
94+
]);
95+
96+
$form->addField('className', [
97+
'type' => 'select',
98+
'title' => 'Import Type',
99+
'default_value' => '',
100+
'options' => $exportableClasses,
101+
'validate' => ['required'],
102+
]);
103+
104+
$form->addField('csvfile', [
105+
'type' => 'file',
106+
'title' => 'Upload CSV',
107+
'default_value' => '',
108+
'destination' => $this->getApp()->getDir(App::TMP),
109+
]);
110+
111+
$this->addSubmitButton($form);
112+
113+
return $form;
114+
}
115+
116+
/**
117+
* {@inheritdocs}
118+
*
119+
* @param FAPI\Form $form
120+
* @param array &$form_state
121+
* @return bool|string
122+
*/
123+
public function formValidate(FAPI\Form $form, &$form_state): bool|string
124+
{
125+
$values = $form->values();
126+
127+
$className = $values['className'];
128+
$modelHeader = array_map(fn($el) => $el['column_name'], $this->containerCall([$className, 'getExportHeader']));
129+
130+
$csvFile = $values->csvfile->filepath;
131+
if (($handle = fopen($csvFile, "r")) !== FALSE) {
132+
if (($firstLine = fgetcsv($handle, 1000, ",")) !== FALSE) {
133+
if (empty(array_diff($firstLine, $modelHeader))) {
134+
return true;
135+
}
136+
}
137+
fclose($handle);
138+
}
139+
140+
$form->addError("Invalid import file", __CLASS__.'::'.__FUNCTION__);
141+
return false;
142+
}
143+
144+
/**
145+
* {@inheritdocs}
146+
*
147+
* @param FAPI\Form $form
148+
* @param array &$form_state
149+
* @return mixed
150+
* @throws BasicException
151+
* @throws DependencyException
152+
* @throws NotFoundException
153+
*/
154+
public function formSubmitted(FAPI\Form $form, &$form_state): mixed
155+
{
156+
$values = $form->values();
157+
158+
$className = $values['className'];
159+
$csvFile = $values->csvfile->filepath;
160+
161+
$csvData = $this->getUtils()->csv2array($csvFile);
162+
$primaryKey = $this->containerCall([$className, 'getKeyField']);
163+
if (!is_array($primaryKey)) {
164+
$primaryKey = [$primaryKey];
165+
}
166+
167+
foreach($csvData as $item) {
168+
if (empty(array_diff($primaryKey, array_keys($item)))) {
169+
// key values are present - loadByObjectIdentifier
170+
171+
$id = [];
172+
foreach($primaryKey as $kname) {
173+
$id[] = $item[$kname] ?? null;
174+
}
175+
176+
// if only 1 column is present, get value
177+
if (count($id) == 1) {
178+
$id = reset($id);
179+
}
180+
181+
// load or create object
182+
try {
183+
$object = $this->containerCall([$className, 'load'], ['id' => $id]);
184+
} catch (\Exception $e) {
185+
$object = $this->containerCall([$className, 'new']);
186+
}
187+
} else {
188+
// key value is not present, create a new object
189+
$object = $this->containerCall([$className, 'new']);
190+
}
191+
192+
/** @var BaseModel $object */
193+
foreach ($item as $key => $value) {
194+
$object->{$key} = $value;
195+
}
196+
197+
$object->persist();
198+
}
199+
200+
unlink($csvFile);
201+
202+
return $this->doRedirect($this->getControllerUrl());
203+
}
204+
}

0 commit comments

Comments
 (0)