These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace HDNET\Importr\Service\Targets; |
||
3 | |||
4 | use HDNET\Importr\Domain\Model\Strategy; |
||
5 | use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; |
||
6 | use HDNET\Importr\Utility; |
||
7 | |||
8 | /** |
||
9 | * Imports records from a .CSV file into the target table which you |
||
10 | * can specify on the target section in your strategy. |
||
11 | * If a record does not exist in the table, it will be inserted, |
||
12 | * otherwise it will be just updated. No duplicates are created. |
||
13 | * |
||
14 | * complete example (strategy target): |
||
15 | * |
||
16 | * HDNET\Importr\Service\Targets\InsertUpdateTable: |
||
17 | * model: TYPO3\CMS\Extbase\Domain\Model\FrontendUser |
||
18 | * repository: TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository |
||
19 | * target_table: fe_users |
||
20 | * exclude_from_update: |
||
21 | * 0: password |
||
22 | * 1: first_name |
||
23 | * 2: zip |
||
24 | * pid: 324 |
||
25 | * mapping: |
||
26 | * 0: username |
||
27 | * 1: password |
||
28 | * 2: usergroup |
||
29 | * 3: name |
||
30 | * 4: first_name |
||
31 | * 5: address |
||
32 | * 6: telephone |
||
33 | * 7: email |
||
34 | * 8: zip |
||
35 | * 9: city |
||
36 | * 10: company |
||
37 | * |
||
38 | * Example CSV: |
||
39 | * |
||
40 | * username;password;usergroup;name;first_name;address;telephone;email;zip;city;company |
||
41 | * EduardFekete;PW123;3;Fekete;Eduard; Example 21; +049123456789;[email protected];91550;Feuchtwangen;MB Connect Line GmbH |
||
42 | * HansVader;PW1234;3;Vader;Hans; Example 22; +049123456710;[email protected];99900;Universe;Hollywood Studios |
||
43 | * |
||
44 | * ------------------------------------------------------------------------------------------------ |
||
45 | * |
||
46 | * exclude_from_update: the elements specified in this array, are never being updated |
||
47 | * |
||
48 | * ------------------------------------------------------------------------------------------------ |
||
49 | * @author Eduard Fekete |
||
50 | */ |
||
51 | |||
52 | class InsertUpdateTable extends AbstractTarget implements TargetInterface |
||
53 | { |
||
54 | /** |
||
55 | * @var array |
||
56 | */ |
||
57 | protected $table_records; |
||
58 | |||
59 | /** |
||
60 | * @var array |
||
61 | */ |
||
62 | protected $configuration; |
||
63 | |||
64 | /** |
||
65 | * @var string |
||
66 | */ |
||
67 | protected $firstTime = "1"; |
||
68 | |||
69 | /** |
||
70 | * @var Strategy |
||
71 | */ |
||
72 | protected $strategy; |
||
73 | |||
74 | /** |
||
75 | * @return array |
||
76 | */ |
||
77 | View Code Duplication | public function getConfiguration() |
|
0 ignored issues
–
show
|
|||
78 | { |
||
79 | $configuration = parent::getConfiguration(); |
||
80 | if (!isset($configuration['pid']) || !is_numeric($configuration['pid'])) { |
||
81 | $configuration['pid'] = 0; |
||
82 | } |
||
83 | |||
84 | return $configuration; |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * @param \HDNET\Importr\Domain\Model\Strategy $strategy |
||
89 | * |
||
90 | * @return void |
||
91 | */ |
||
92 | public function start(Strategy $strategy) |
||
93 | { |
||
94 | $this->strategy = $strategy; |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Process every entry in the .csv |
||
99 | * |
||
100 | * @param array $entry |
||
101 | * |
||
102 | * @return int|void |
||
103 | */ |
||
104 | public function processEntry(array $entry) |
||
105 | { |
||
106 | $record_exists = false; |
||
107 | $entry_username = $entry['0']; |
||
108 | |||
109 | $this->configuration = $this->getConfiguration(); |
||
110 | |||
111 | if ($this->firstTime == "1") { |
||
112 | $this->firstTime = 0; |
||
0 ignored issues
–
show
The property
$firstTime was declared of type string , but 0 is of type integer . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
Loading history...
|
|||
113 | $this->getRecords("*"); |
||
114 | } |
||
115 | |||
116 | foreach ($this->table_records as $record) { |
||
117 | if ($record['deleted'] == 0) { |
||
118 | if ($record['username'] == $entry_username) { |
||
119 | $record_exists = true; |
||
120 | break; |
||
121 | } |
||
122 | } else { |
||
123 | continue; |
||
124 | } |
||
125 | } |
||
126 | |||
127 | if ($record_exists) { |
||
128 | $this->updateRecord($entry); |
||
129 | return TargetInterface::RESULT_UPDATE; |
||
130 | } else { |
||
131 | $this->insertRecord($entry); |
||
132 | return TargetInterface::RESULT_INSERT; |
||
133 | } |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * |
||
138 | * Fetch all records from the target table, where the PID equals the PID specified |
||
139 | * in the target section of the strategy |
||
140 | * |
||
141 | * @return void |
||
142 | */ |
||
143 | public function getRecords($selectFields) |
||
0 ignored issues
–
show
getRecords uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
144 | { |
||
145 | $fromTable = $this->configuration['target_table']; |
||
146 | $whereStatement = "pid = '".$this->configuration['pid']."'"; |
||
147 | |||
148 | $GLOBALS['TYPO3_DB']->store_lastBuiltQuery = 1; |
||
149 | |||
150 | $this->table_records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows( |
||
151 | $selectFields, |
||
152 | $fromTable, |
||
153 | $whereStatement |
||
154 | ); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Insert record into the target table which you have specified in the target section of the strategy |
||
159 | * |
||
160 | * @param array $entry |
||
161 | * |
||
162 | * @return void |
||
163 | */ |
||
164 | public function insertRecord(array $entry) |
||
0 ignored issues
–
show
insertRecord uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
165 | { |
||
166 | $field_values = array(); |
||
167 | $into_table = $this->configuration['target_table']; |
||
168 | |||
169 | foreach ($this->configuration["mapping"] as $key => $value) { |
||
170 | $field_values[$value] = $entry[$key]; |
||
171 | } |
||
172 | |||
173 | $field_values['pid'] = $this->configuration['pid']; |
||
174 | $field_values['tstamp'] = time(); |
||
175 | $field_values['crdate'] = time(); |
||
176 | |||
177 | $GLOBALS['TYPO3_DB']->exec_INSERTquery($into_table, $field_values); |
||
178 | $GLOBALS['TYPO3_DB']->sql_insert_id(); |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Update a record in the target table which you have specified in the |
||
183 | * target section of the strategy (don't update the password) |
||
184 | * |
||
185 | * @param array $entry |
||
186 | * |
||
187 | * @return void |
||
188 | */ |
||
189 | public function updateRecord(array $entry) |
||
0 ignored issues
–
show
updateRecord uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
190 | { |
||
191 | $into_table = $this->configuration['target_table']; |
||
192 | $whereStatement = "pid = '".$this->configuration['pid']."' AND username = '".$entry[0]."'"; |
||
193 | |||
194 | $field_values = array(); |
||
0 ignored issues
–
show
$field_values is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
195 | $tmp_arr = array(); |
||
196 | |||
197 | foreach ($this->configuration["mapping"] as $key => $value) { |
||
198 | $tmp_arr[$value] = $entry[$key]; |
||
199 | } |
||
200 | |||
201 | $field_values = $this->duplicateArray($tmp_arr, $this->configuration['exclude_from_update']); |
||
202 | $field_values['tstamp'] = time(); |
||
203 | |||
204 | $res = $GLOBALS['TYPO3_DB']->exec_UPDATEquery($into_table, $whereStatement, $field_values); |
||
0 ignored issues
–
show
$res is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
205 | $cnt = $GLOBALS['TYPO3_DB']->sql_affected_rows(); |
||
0 ignored issues
–
show
$cnt is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
206 | } |
||
207 | |||
208 | /** |
||
209 | * This function creates a duplicate of a associative array and optionally removes |
||
210 | * any entries which are also elements of a second array |
||
211 | * |
||
212 | * @param array $arr |
||
213 | * @param array $exclude_arr |
||
214 | * |
||
215 | * @return array |
||
216 | */ |
||
217 | public function duplicateArray(array $arr, array $exclude_arr = null) |
||
218 | { |
||
219 | $exclude = false; |
||
220 | |||
221 | if ($exclude_arr != null) { |
||
222 | $exclude_max = count($exclude_arr); |
||
223 | if (count($exclude_arr) > 0) { |
||
224 | $exclude = true; |
||
225 | } |
||
226 | |||
227 | foreach ($arr as $parentkey => $parentvalue) { |
||
228 | $chk = $exclude_max; |
||
0 ignored issues
–
show
$chk is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
229 | |||
230 | if ($exclude) { |
||
231 | foreach ($exclude_arr as $key => $value) { |
||
232 | if ($value == $parentkey) { |
||
233 | unset($arr[$parentkey]); |
||
234 | } |
||
235 | } |
||
236 | } |
||
237 | } |
||
238 | } |
||
239 | |||
240 | return $arr; |
||
241 | } |
||
242 | |||
243 | public function end() |
||
244 | { |
||
245 | } |
||
246 | } |
||
247 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.