Completed
Push — master ( 7f2d14...7fc8f2 )
by Fabien
02:11
created
Classes/Controller/ContentController.php 2 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -740,11 +740,11 @@
 block discarded – undo
740 740
      * Signal that is called for post-processing content data send to the server for update.
741 741
      *
742 742
      * @param Content $contentObject
743
-     * @param $fieldNameAndPath
743
+     * @param string $fieldNameAndPath
744 744
      * @param $contentData
745
-     * @param $counter
746
-     * @param $savingBehavior
747
-     * @param $language
745
+     * @param integer $counter
746
+     * @param string $savingBehavior
747
+     * @param integer $language
748 748
      * @return ProcessContentDataSignalArguments
749 749
      */
750 750
     protected function emitProcessContentDataSignal(Content $contentObject, $fieldNameAndPath, $contentData, $counter, $savingBehavior, $language)
Please login to merge, or discard this patch.
Indentation   +758 added lines, -758 removed lines patch added patch discarded remove patch
@@ -42,763 +42,763 @@
 block discarded – undo
42 42
 class ContentController extends ActionController
43 43
 {
44 44
 
45
-    /**
46
-     * @var \Fab\Vidi\Domain\Repository\SelectionRepository
47
-     * @inject
48
-     */
49
-    protected $selectionRepository;
50
-
51
-    /**
52
-     * Initialize every action.
53
-     */
54
-    public function initializeAction()
55
-    {
56
-        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
57
-        $pageRenderer->addInlineLanguageLabelFile('EXT:vidi/Resources/Private/Language/locallang.xlf');
58
-
59
-        // Configure property mapping to retrieve the file object.
60
-        if ($this->arguments->hasArgument('columns')) {
61
-
62
-            /** @var CsvToArrayConverter $typeConverter */
63
-            $typeConverter = $this->objectManager->get(CsvToArrayConverter::class);
64
-
65
-            $propertyMappingConfiguration = $this->arguments->getArgument('columns')->getPropertyMappingConfiguration();
66
-            $propertyMappingConfiguration->setTypeConverter($typeConverter);
67
-        }
68
-    }
69
-
70
-    /**
71
-     * List action for this controller.
72
-     *
73
-     * @return void
74
-     */
75
-    public function indexAction()
76
-    {
77
-        $dataType = $this->getModuleLoader()->getDataType();
78
-        $selections = $this->selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
79
-        $this->view->assign('selections', $selections);
80
-
81
-        $columns = Tca::grid()->getFields();
82
-        $this->view->assign('columns', $columns);
83
-        $this->view->assign('numberOfColumns', count($columns));
84
-    }
85
-
86
-    /**
87
-     * List Row action for this controller. Output a json list of contents
88
-     *
89
-     * @param array $columns corresponds to columns to be rendered.
90
-     * @param array $matches
91
-     * @validate $columns Fab\Vidi\Domain\Validator\ColumnsValidator
92
-     * @validate $matches Fab\Vidi\Domain\Validator\MatchesValidator
93
-     * @return void
94
-     */
95
-    public function listAction(array $columns = [], $matches = [])
96
-    {
97
-        // Initialize some objects related to the query.
98
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
99
-        $order = OrderObjectFactory::getInstance()->getOrder();
100
-        $pager = PagerObjectFactory::getInstance()->getPager();
101
-
102
-        // Fetch objects via the Content Service.
103
-        $contentService = $this->getContentService()->findBy($matcher, $order, $pager->getLimit(), $pager->getOffset());
104
-        $pager->setCount($contentService->getNumberOfObjects());
105
-
106
-        // Assign values.
107
-        $this->view->assign('columns', $columns);
108
-        $this->view->assign('objects', $contentService->getObjects());
109
-        $this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
110
-        $this->view->assign('pager', $pager);
111
-        $this->view->assign('response', $this->response);
112
-    }
113
-
114
-    /**
115
-     * Retrieve Content objects first according to matching criteria and then "update" them.
116
-     * Important to notice the field name can contains a path, e.g. metadata.title and therefore must be analysed.
117
-     *
118
-     * Possible values for $matches:
119
-     * -----------------------------
120
-     *
121
-     * $matches = array(uid => 1), will be taken as $query->equals
122
-     * $matches = array(uid => 1,2,3), will be taken as $query->in
123
-     * $matches = array(field_name1 => bar, field_name2 => bax), will be separated by AND.
124
-     *
125
-     * Possible values for $content:
126
-     * -----------------------------
127
-     *
128
-     * $content = array(field_name => bar)
129
-     * $content = array(field_name => array(value1, value2)) <-- will be CSV converted by "value1,value2"
130
-     *
131
-     * @param string $fieldNameAndPath
132
-     * @param array $content
133
-     * @param array $matches
134
-     * @param string $savingBehavior
135
-     * @param int $language
136
-     * @param array $columns
137
-     * @return string
138
-     * @throws \Fab\Vidi\Exception\InvalidKeyInArrayException
139
-     */
140
-    public function updateAction($fieldNameAndPath, array $content, array $matches = [], $savingBehavior = SavingBehavior::REPLACE, $language = 0, $columns = [])
141
-    {
142
-
143
-        // Instantiate the Matcher object according different rules.
144
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
145
-        $order = OrderObjectFactory::getInstance()->getOrder();
146
-
147
-        // Fetch objects via the Content Service.
148
-        $contentService = $this->getContentService()->findBy($matcher, $order);
149
-
150
-        // Get the real field that is going to be updated.
151
-        $updatedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
152
-
153
-        // Get result object for storing data along the processing.
154
-        $result = $this->getJsonResult();
155
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
156
-
157
-        foreach ($contentService->getObjects() as $index => $object) {
158
-
159
-            $identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid', $language);
160
-
161
-            // It could be the identifier is not found because the translation
162
-            // of the record does not yet exist when mass-editing
163
-            if ((int)$identifier <= 0) {
164
-                continue;
165
-            }
166
-
167
-            $dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
168
-
169
-            $signalResult = $this->emitProcessContentDataSignal($object, $fieldNameAndPath, $content, $index + 1, $savingBehavior, $language);
170
-            $contentData = $signalResult->getContentData();
171
-
172
-            // Add identifier to content data, required by TCEMain.
173
-            $contentData['uid'] = $identifier;
174
-
175
-            /** @var Content $dataObject */
176
-            $dataObject = GeneralUtility::makeInstance(Content::class, $dataType, $contentData);
177
-
178
-            // Properly update object.
179
-            ContentRepositoryFactory::getInstance($dataType)->update($dataObject);
180
-
181
-            // Get the possible error messages and store them.
182
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
183
-            $result->addErrorMessages($errorMessages);
184
-
185
-            // We only want to see the detail result if there is one object updated.
186
-            // Required for inline editing + it will display some useful info on the GUI in the flash messages.
187
-            if ($contentService->getNumberOfObjects() === 1) {
188
-
189
-                // Fetch the updated object from repository.
190
-                $updatedObject = ContentRepositoryFactory::getInstance()->findByUid($object->getUid());
191
-
192
-                // Re-fetch the updated result.
193
-                $updatedResult = $this->getContentObjectResolver()->getValue($updatedObject, $fieldNameAndPath, $updatedFieldName, $language);
194
-                if (is_array($updatedResult)) {
195
-                    $_updatedResult = []; // reset result set.
196
-
197
-                    /** @var Content $contentObject */
198
-                    foreach ($updatedResult as $contentObject) {
199
-                        $labelField = Tca::table($contentObject)->getLabelField();
200
-                        $values = array(
201
-                            'uid' => $contentObject->getUid(),
202
-                            'name' => $contentObject[$labelField],
203
-                        );
204
-                        $_updatedResult[] = $values;
205
-                    }
206
-
207
-                    $updatedResult = $_updatedResult;
208
-                }
209
-
210
-                $labelField = Tca::table($object)->getLabelField();
211
-
212
-                $processedObjectData = array(
213
-                    'uid' => $object->getUid(),
214
-                    'name' => $object[$labelField],
215
-                    'updatedField' => $fieldNameAndPath,
216
-                    'updatedValue' => $updatedResult,
217
-                );
218
-                $result->setProcessedObject($processedObjectData);
219
-
220
-                if (!empty($columns)) {
221
-                    /** @var Row $row */
222
-                    $row = GeneralUtility::makeInstance(\Fab\Vidi\View\Grid\Row::class, $columns);
223
-                    $result->setRow($row->render($updatedObject));
224
-                }
225
-            }
226
-        }
227
-
228
-        // Set the result and render the JSON view.
229
-        $this->getJsonView()->setResult($result);
230
-        return $this->getJsonView()->render();
231
-    }
232
-
233
-    /**
234
-     * Set the sorting of a record giving the previous object.
235
-     *
236
-     * @param array $matches
237
-     * @param int $previousIdentifier
238
-     * @return string
239
-     */
240
-    public function sortAction(array $matches = [], $previousIdentifier = null)
241
-    {
242
-
243
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
244
-
245
-        // Fetch objects via the Content Service.
246
-        $contentService = $this->getContentService()->findBy($matcher);
247
-
248
-        // Compute the label field name of the table.
249
-        $tableTitleField = Tca::table()->getLabelField();
250
-
251
-        // Get result object for storing data along the processing.
252
-        $result = $this->getJsonResult();
253
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
254
-
255
-        foreach ($contentService->getObjects() as $object) {
256
-
257
-            // Store the first object, so that the "action" message can be more explicit when deleting only one record.
258
-            if ($contentService->getNumberOfObjects() === 1) {
259
-                $tableTitleValue = $object[$tableTitleField];
260
-                $processedObjectData = array(
261
-                    'uid' => $object->getUid(),
262
-                    'name' => $tableTitleValue,
263
-                );
264
-                $result->setProcessedObject($processedObjectData);
265
-            }
266
-
267
-            // The $target corresponds to the pid to move the records to.
268
-            // It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
269
-            $target = is_null($previousIdentifier) ? $object->getPid() : (-(int)$previousIdentifier);
270
-
271
-            // Work out the object.
272
-            ContentRepositoryFactory::getInstance()->move($object, $target);
273
-
274
-            // Get the possible error messages and store them.
275
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
276
-            $result->addErrorMessages($errorMessages);
277
-        }
278
-
279
-        // Set the result and render the JSON view.
280
-        $this->getJsonView()->setResult($result);
281
-        return $this->getJsonView()->render();
282
-    }
283
-
284
-    /**
285
-     * Returns an editing form for a given field name of a Content object.
286
-     * Argument $fieldNameAndPath corresponds to the field name to be edited.
287
-     * Important to notice it can contains a path, e.g. metadata.title and therefore must be analysed.
288
-     *
289
-     * Possible values for $matches, refer to method "updateAction".
290
-     *
291
-     * @param string $fieldNameAndPath
292
-     * @param array $matches
293
-     * @param bool $hasRecursiveSelection
294
-     * @throws \Exception
295
-     */
296
-    public function editAction($fieldNameAndPath, array $matches = [], $hasRecursiveSelection = false)
297
-    {
298
-
299
-        // Instantiate the Matcher object according different rules.
300
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
301
-
302
-        // Fetch objects via the Content Service.
303
-        $contentService = $this->getContentService()->findBy($matcher);
304
-
305
-        $dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
306
-        $fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
307
-
308
-        $fieldType = Tca::table($dataType)->field($fieldName)->getType();
309
-        $this->view->assign('fieldType', ucfirst($fieldType));
310
-        $this->view->assign('dataType', $dataType);
311
-        $this->view->assign('fieldName', $fieldName);
312
-        $this->view->assign('matches', $matches);
313
-        $this->view->assign('fieldNameAndPath', $fieldNameAndPath);
314
-        $this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
315
-        $this->view->assign('hasRecursiveSelection', $hasRecursiveSelection);
316
-        $this->view->assign('editWholeSelection', empty($matches['uid'])); // necessary??
317
-
318
-        // Fetch content and its relations.
319
-        if ($fieldType === FieldType::MULTISELECT) {
320
-
321
-            $object = ContentRepositoryFactory::getInstance()->findOneBy($matcher);
322
-            $identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid');
323
-            $dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
324
-
325
-            $content = ContentRepositoryFactory::getInstance($dataType)->findByUid($identifier);
326
-
327
-            // Makes sure the object was retrieved. Security!
328
-            if (!$content) {
329
-                $message = sprintf('I could not retrieved content object of type "%s" with identifier %s.', $dataType, $identifier);
330
-                throw new \Exception($message, 1402350182);
331
-            }
332
-
333
-            $relatedDataType = Tca::table($dataType)->field($fieldName)->getForeignTable();
334
-
335
-            // Initialize the matcher object.
336
-            /** @var Matcher $matcher */
337
-            $matcher = GeneralUtility::makeInstance(Matcher::class, [], $relatedDataType);
338
-
339
-            // Default ordering for related data type.
340
-            $defaultOrderings = Tca::table($relatedDataType)->getDefaultOrderings();
341
-            /** @var Order $order */
342
-            $defaultOrder = GeneralUtility::makeInstance(Order::class, $defaultOrderings);
343
-
344
-            // Fetch related contents
345
-            $relatedContents = ContentRepositoryFactory::getInstance($relatedDataType)->findBy($matcher, $defaultOrder);
346
-
347
-            if (Tca::table($dataType)->field($fieldName)->isRenderModeTree()) {
348
-
349
-                $fieldConfiguration = Tca::table($dataType)->field($fieldName)->getConfiguration();
350
-                $parentField = $fieldConfiguration['treeConfig']['parentField'];
351
-
352
-                $flatTree = [];
353
-                foreach ($relatedContents as $node) {
354
-                    $flatTree[$node->getUid()] = array(
355
-                        'item' => $node,
356
-                        'parent' => $node[$parentField] ? $node[$parentField]['uid'] : null,
357
-                    );
358
-                }
359
-
360
-                $tree = [];
361
-
362
-                // If leaves are selected without its parents selected, those are shown as parent
363
-                foreach ($flatTree as $id => &$flatNode) {
364
-                    if (!isset($flatTree[$flatNode['parent']])) {
365
-                        $flatNode['parent'] = null;
366
-                    }
367
-                }
368
-
369
-                foreach ($flatTree as $id => &$node) {
370
-                    if ($node['parent'] === null) {
371
-                        $tree[$id] = &$node;
372
-                    } else {
373
-                        $flatTree[$node['parent']]['children'][$id] = &$node;
374
-                    }
375
-                }
376
-
377
-                $relatedContents = $tree;
378
-            }
379
-
380
-            $this->view->assign('content', $content);
381
-            $this->view->assign('relatedContents', $relatedContents);
382
-            $this->view->assign('relatedDataType', $relatedDataType);
383
-            $this->view->assign('relatedContentTitle', Tca::table($relatedDataType)->getTitle());
384
-            $this->view->assign(
385
-                'renderMode',
386
-                Tca::table($dataType)->field($fieldName)->isRenderModeTree() ? FieldType::TREE : null
387
-            );
388
-        }
389
-    }
390
-
391
-    /**
392
-     * Retrieve Content objects first according to matching criteria and then "delete" them.
393
-     *
394
-     * Possible values for $matches, refer to method "updateAction".
395
-     *
396
-     * @param array $matches
397
-     * @return string
398
-     */
399
-    public function deleteAction(array $matches = [])
400
-    {
401
-
402
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
403
-
404
-        // Fetch objects via the Content Service.
405
-        $contentService = $this->getContentService()->findBy($matcher);
406
-
407
-        // Compute the label field name of the table.
408
-        $tableTitleField = Tca::table()->getLabelField();
409
-
410
-        // Get result object for storing data along the processing.
411
-        $result = $this->getJsonResult();
412
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
413
-
414
-        foreach ($contentService->getObjects() as $object) {
415
-
416
-            // Store the first object, so that the delete message can be more explicit when deleting only one record.
417
-            if ($contentService->getNumberOfObjects() === 1) {
418
-                $tableTitleValue = $object[$tableTitleField];
419
-                $processedObjectData = array(
420
-                    'uid' => $object->getUid(),
421
-                    'name' => $tableTitleValue,
422
-                );
423
-                $result->setProcessedObject($processedObjectData);
424
-            }
425
-
426
-            // Properly delete object.
427
-            ContentRepositoryFactory::getInstance()->remove($object);
428
-
429
-            // Get the possible error messages and store them.
430
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
431
-            $result->addErrorMessages($errorMessages);
432
-        }
433
-
434
-        // Set the result and render the JSON view.
435
-        $this->getJsonView()->setResult($result);
436
-        return $this->getJsonView()->render();
437
-    }
438
-
439
-    /**
440
-     * Retrieve Content objects first according to matching criteria and then "copy" them.
441
-     *
442
-     * Possible values for $matches, refer to method "updateAction".
443
-     *
444
-     * @param string $target
445
-     * @param array $matches
446
-     * @throws \Exception
447
-     * @return string
448
-     */
449
-    public function copyAction($target, array $matches = [])
450
-    {
451
-        // @todo
452
-        throw new \Exception('Not yet implemented', 1410192546);
453
-    }
454
-
455
-    /**
456
-     * Retrieve Content objects from the Clipboard then "copy" them according to the target.
457
-     *
458
-     * @param string $target
459
-     * @throws \Exception
460
-     * @return string
461
-     */
462
-    public function copyClipboardAction($target)
463
-    {
464
-
465
-        // Retrieve matcher object from clipboard.
466
-        $matcher = $this->getClipboardService()->getMatcher();
467
-
468
-        // Fetch objects via the Content Service.
469
-        $contentService = $this->getContentService()->findBy($matcher);
470
-
471
-        // Compute the label field name of the table.
472
-        $tableTitleField = Tca::table()->getLabelField();
473
-
474
-        // Get result object for storing data along the processing.
475
-        $result = $this->getJsonResult();
476
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
477
-
478
-        foreach ($contentService->getObjects() as $object) {
479
-
480
-            // Store the first object, so that the "action" message can be more explicit when deleting only one record.
481
-            if ($contentService->getNumberOfObjects() === 1) {
482
-                $tableTitleValue = $object[$tableTitleField];
483
-                $processedObjectData = array(
484
-                    'uid' => $object->getUid(),
485
-                    'name' => $tableTitleValue,
486
-                );
487
-                $result->setProcessedObject($processedObjectData);
488
-            }
489
-
490
-            // Work out the object.
491
-            ContentRepositoryFactory::getInstance()->copy($object, $target);
492
-
493
-            // Get the possible error messages and store them.
494
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
495
-            $result->addErrorMessages($errorMessages);
496
-        }
497
-
498
-        // Flush Clipboard if told so.
499
-        if (GeneralUtility::_GP('flushClipboard')) {
500
-            $this->getClipboardService()->flush();
501
-        }
502
-
503
-        // Set the result and render the JSON view.
504
-        $this->getJsonView()->setResult($result);
505
-        return $this->getJsonView()->render();
506
-    }
507
-
508
-    /**
509
-     * Retrieve Content objects first according to matching criteria and then "move" them.
510
-     *
511
-     * Possible values for $matches, refer to method "updateAction".
512
-     *
513
-     * @param string $target
514
-     * @param array $matches
515
-     * @return string
516
-     */
517
-    public function moveAction($target, array $matches = [])
518
-    {
519
-
520
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
521
-
522
-        // Fetch objects via the Content Service.
523
-        $contentService = $this->getContentService()->findBy($matcher);
524
-
525
-        // Compute the label field name of the table.
526
-        $tableTitleField = Tca::table()->getLabelField();
527
-
528
-        // Get result object for storing data along the processing.
529
-        $result = $this->getJsonResult();
530
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
531
-
532
-        foreach ($contentService->getObjects() as $object) {
533
-
534
-            // Store the first object, so that the "action" message can be more explicit when deleting only one record.
535
-            if ($contentService->getNumberOfObjects() === 1) {
536
-                $tableTitleValue = $object[$tableTitleField];
537
-                $processedObjectData = array(
538
-                    'uid' => $object->getUid(),
539
-                    'name' => $tableTitleValue,
540
-                );
541
-                $result->setProcessedObject($processedObjectData);
542
-            }
543
-
544
-            // Work out the object.
545
-            ContentRepositoryFactory::getInstance()->move($object, $target);
546
-
547
-            // Get the possible error messages and store them.
548
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
549
-            $result->addErrorMessages($errorMessages);
550
-        }
551
-
552
-        // Set the result and render the JSON view.
553
-        $this->getJsonView()->setResult($result);
554
-        return $this->getJsonView()->render();
555
-    }
556
-
557
-    /**
558
-     * Retrieve Content objects from the Clipboard then "move" them according to the target.
559
-     *
560
-     * @param string $target
561
-     * @return string
562
-     */
563
-    public function moveClipboardAction($target)
564
-    {
565
-
566
-        // Retrieve matcher object from clipboard.
567
-        $matcher = $this->getClipboardService()->getMatcher();
568
-
569
-        // Fetch objects via the Content Service.
570
-        $contentService = $this->getContentService()->findBy($matcher);
571
-
572
-        // Compute the label field name of the table.
573
-        $tableTitleField = Tca::table()->getLabelField();
574
-
575
-        // Get result object for storing data along the processing.
576
-        $result = $this->getJsonResult();
577
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
578
-
579
-        foreach ($contentService->getObjects() as $object) {
580
-
581
-            // Store the first object, so that the "action" message can be more explicit when deleting only one record.
582
-            if ($contentService->getNumberOfObjects() === 1) {
583
-                $tableTitleValue = $object[$tableTitleField];
584
-                $processedObjectData = array(
585
-                    'uid' => $object->getUid(),
586
-                    'name' => $tableTitleValue,
587
-                );
588
-                $result->setProcessedObject($processedObjectData);
589
-            }
590
-
591
-            // Work out the object.
592
-            ContentRepositoryFactory::getInstance()->move($object, $target);
593
-
594
-            // Get the possible error messages and store them.
595
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
596
-            $result->addErrorMessages($errorMessages);
597
-        }
598
-
599
-        // Flush Clipboard if told so.
600
-        if (GeneralUtility::_GP('flushClipboard')) {
601
-            $this->getClipboardService()->flush();
602
-        }
603
-
604
-        // Set the result and render the JSON view.
605
-        $this->getJsonView()->setResult($result);
606
-        return $this->getJsonView()->render();
607
-    }
608
-
609
-    /**
610
-     * Retrieve Content objects first according to matching criteria and then "localize" them.
611
-     *
612
-     * Possible values for $matches, refer to method "updateAction".
613
-     *
614
-     * @param string $fieldNameAndPath
615
-     * @param array $matches
616
-     * @param int $language
617
-     * @return string
618
-     * @throws \Exception
619
-     */
620
-    public function localizeAction($fieldNameAndPath, array $matches = [], $language = 0)
621
-    {
622
-
623
-        $matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
624
-
625
-        // Fetch objects via the Content Service.
626
-        $contentService = $this->getContentService()->findBy($matcher);
627
-
628
-        // Get result object for storing data along the processing.
629
-        $result = $this->getJsonResult();
630
-        $result->setNumberOfObjects($contentService->getNumberOfObjects());
631
-
632
-        foreach ($contentService->getObjects() as $object) {
633
-
634
-            $identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid');
635
-            $dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
636
-
637
-            // Fetch the source object to be localized.
638
-            /** @var Content $content */
639
-            $content = ContentRepositoryFactory::getInstance($dataType)->findByIdentifier($identifier);
640
-
641
-            // Makes sure the object was retrieved. Security!
642
-            if (!$content) {
643
-                $message = sprintf('Something went wrong when retrieving content "%s" with identifier "%s".', $dataType, $identifier);
644
-                throw new \Exception($message, 1412343097);
645
-            }
646
-
647
-            // Handover the localization to the Repository.
648
-            ContentRepositoryFactory::getInstance($dataType)->localize($content, $language);
649
-
650
-            // Get the possible error messages and store them.
651
-            $errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
652
-
653
-            // Redirect to TCEForm so that the BE User can do its job!
654
-            if ($contentService->getNumberOfObjects() === 1) {
655
-
656
-                if (!empty($errorMessages)) {
657
-                    $message = sprintf('Something went wrong when localizing content "%s" with identifier "%s". <br/>%s',
658
-                        $dataType,
659
-                        $identifier,
660
-                        implode('<br/>', $errorMessages)
661
-                    );
662
-                    throw new \Exception($message, 1412343098);
663
-                }
664
-
665
-                $localizedContent = $this->getLanguageService()->getLocalizedContent($content, $language);
666
-                if (empty($localizedContent)) {
667
-                    $message = sprintf('Oups! I could not retrieve localized content of type "%s" with identifier "%s"',
668
-                        $content->getDataType(),
669
-                        $content->getUid()
670
-                    );
671
-                    throw new \Exception($message, 1412343099);
672
-                }
673
-
674
-                /** @var EditUri $uri */
675
-                $uriRenderer = GeneralUtility::makeInstance(EditUri::class);
676
-                $uri = $uriRenderer->render($localizedContent);
677
-                HttpUtility::redirect($uri);
678
-                break; // no need to further continue
679
-            }
680
-
681
-            $result->addErrorMessages($errorMessages);
682
-        }
683
-
684
-        // Set the result and render the JSON view.
685
-        $this->getJsonView()->setResult($result);
686
-        return $this->getJsonView()->render();
687
-    }
688
-
689
-    /**
690
-     * Get the Vidi Module Loader.
691
-     *
692
-     * @return ContentService
693
-     */
694
-    protected function getContentService()
695
-    {
696
-        return GeneralUtility::makeInstance(ContentService::class);
697
-    }
698
-
699
-    /**
700
-     * @return ContentObjectResolver
701
-     */
702
-    protected function getContentObjectResolver()
703
-    {
704
-        return GeneralUtility::makeInstance(ContentObjectResolver::class);
705
-    }
706
-
707
-    /**
708
-     * @return FieldPathResolver
709
-     */
710
-    protected function getFieldPathResolver()
711
-    {
712
-        return GeneralUtility::makeInstance(FieldPathResolver::class);
713
-    }
714
-
715
-    /**
716
-     * Return a special view for handling JSON
717
-     * Goal is to have this view injected but require more configuration.
718
-     *
719
-     * @return JsonView
720
-     */
721
-    protected function getJsonView()
722
-    {
723
-        if (!$this->view instanceof JsonView) {
724
-            /** @var JsonView $view */
725
-            $this->view = $this->objectManager->get(JsonView::class);
726
-            $this->view->setResponse($this->response);
727
-        }
728
-        return $this->view;
729
-    }
730
-
731
-    /**
732
-     * @return JsonResult|object
733
-     */
734
-    protected function getJsonResult()
735
-    {
736
-        return GeneralUtility::makeInstance(JsonResult::class);
737
-    }
738
-
739
-    /**
740
-     * Signal that is called for post-processing content data send to the server for update.
741
-     *
742
-     * @param Content $contentObject
743
-     * @param $fieldNameAndPath
744
-     * @param $contentData
745
-     * @param $counter
746
-     * @param $savingBehavior
747
-     * @param $language
748
-     * @return ProcessContentDataSignalArguments
749
-     */
750
-    protected function emitProcessContentDataSignal(Content $contentObject, $fieldNameAndPath, $contentData, $counter, $savingBehavior, $language)
751
-    {
752
-
753
-        /** @var \Fab\Vidi\Signal\ProcessContentDataSignalArguments $signalArguments */
754
-        $signalArguments = GeneralUtility::makeInstance(\Fab\Vidi\Signal\ProcessContentDataSignalArguments::class);
755
-        $signalArguments->setContentObject($contentObject)
756
-            ->setFieldNameAndPath($fieldNameAndPath)
757
-            ->setContentData($contentData)
758
-            ->setCounter($counter)
759
-            ->setSavingBehavior($savingBehavior)
760
-            ->setLanguage($language);
761
-
762
-        $signalResult = $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\Controller\Backend\ContentController', 'processContentData', array($signalArguments));
763
-        return $signalResult[0];
764
-    }
765
-
766
-    /**
767
-     * Get the SignalSlot dispatcher.
768
-     *
769
-     * @return Dispatcher
770
-     */
771
-    protected function getSignalSlotDispatcher()
772
-    {
773
-        return $this->objectManager->get(Dispatcher::class);
774
-    }
775
-
776
-    /**
777
-     * Get the Clipboard service.
778
-     *
779
-     * @return ClipboardService
780
-     */
781
-    protected function getClipboardService()
782
-    {
783
-        return GeneralUtility::makeInstance(ClipboardService::class);
784
-    }
785
-
786
-    /**
787
-     * @return LanguageService
788
-     */
789
-    protected function getLanguageService()
790
-    {
791
-        return GeneralUtility::makeInstance(LanguageService::class);
792
-    }
793
-
794
-    /**
795
-     * Get the Vidi Module Loader.
796
-     *
797
-     * @return ModuleLoader
798
-     */
799
-    protected function getModuleLoader()
800
-    {
801
-        return GeneralUtility::makeInstance(ModuleLoader::class);
802
-    }
45
+	/**
46
+	 * @var \Fab\Vidi\Domain\Repository\SelectionRepository
47
+	 * @inject
48
+	 */
49
+	protected $selectionRepository;
50
+
51
+	/**
52
+	 * Initialize every action.
53
+	 */
54
+	public function initializeAction()
55
+	{
56
+		$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
57
+		$pageRenderer->addInlineLanguageLabelFile('EXT:vidi/Resources/Private/Language/locallang.xlf');
58
+
59
+		// Configure property mapping to retrieve the file object.
60
+		if ($this->arguments->hasArgument('columns')) {
61
+
62
+			/** @var CsvToArrayConverter $typeConverter */
63
+			$typeConverter = $this->objectManager->get(CsvToArrayConverter::class);
64
+
65
+			$propertyMappingConfiguration = $this->arguments->getArgument('columns')->getPropertyMappingConfiguration();
66
+			$propertyMappingConfiguration->setTypeConverter($typeConverter);
67
+		}
68
+	}
69
+
70
+	/**
71
+	 * List action for this controller.
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public function indexAction()
76
+	{
77
+		$dataType = $this->getModuleLoader()->getDataType();
78
+		$selections = $this->selectionRepository->findByDataTypeForCurrentBackendUser($dataType);
79
+		$this->view->assign('selections', $selections);
80
+
81
+		$columns = Tca::grid()->getFields();
82
+		$this->view->assign('columns', $columns);
83
+		$this->view->assign('numberOfColumns', count($columns));
84
+	}
85
+
86
+	/**
87
+	 * List Row action for this controller. Output a json list of contents
88
+	 *
89
+	 * @param array $columns corresponds to columns to be rendered.
90
+	 * @param array $matches
91
+	 * @validate $columns Fab\Vidi\Domain\Validator\ColumnsValidator
92
+	 * @validate $matches Fab\Vidi\Domain\Validator\MatchesValidator
93
+	 * @return void
94
+	 */
95
+	public function listAction(array $columns = [], $matches = [])
96
+	{
97
+		// Initialize some objects related to the query.
98
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
99
+		$order = OrderObjectFactory::getInstance()->getOrder();
100
+		$pager = PagerObjectFactory::getInstance()->getPager();
101
+
102
+		// Fetch objects via the Content Service.
103
+		$contentService = $this->getContentService()->findBy($matcher, $order, $pager->getLimit(), $pager->getOffset());
104
+		$pager->setCount($contentService->getNumberOfObjects());
105
+
106
+		// Assign values.
107
+		$this->view->assign('columns', $columns);
108
+		$this->view->assign('objects', $contentService->getObjects());
109
+		$this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
110
+		$this->view->assign('pager', $pager);
111
+		$this->view->assign('response', $this->response);
112
+	}
113
+
114
+	/**
115
+	 * Retrieve Content objects first according to matching criteria and then "update" them.
116
+	 * Important to notice the field name can contains a path, e.g. metadata.title and therefore must be analysed.
117
+	 *
118
+	 * Possible values for $matches:
119
+	 * -----------------------------
120
+	 *
121
+	 * $matches = array(uid => 1), will be taken as $query->equals
122
+	 * $matches = array(uid => 1,2,3), will be taken as $query->in
123
+	 * $matches = array(field_name1 => bar, field_name2 => bax), will be separated by AND.
124
+	 *
125
+	 * Possible values for $content:
126
+	 * -----------------------------
127
+	 *
128
+	 * $content = array(field_name => bar)
129
+	 * $content = array(field_name => array(value1, value2)) <-- will be CSV converted by "value1,value2"
130
+	 *
131
+	 * @param string $fieldNameAndPath
132
+	 * @param array $content
133
+	 * @param array $matches
134
+	 * @param string $savingBehavior
135
+	 * @param int $language
136
+	 * @param array $columns
137
+	 * @return string
138
+	 * @throws \Fab\Vidi\Exception\InvalidKeyInArrayException
139
+	 */
140
+	public function updateAction($fieldNameAndPath, array $content, array $matches = [], $savingBehavior = SavingBehavior::REPLACE, $language = 0, $columns = [])
141
+	{
142
+
143
+		// Instantiate the Matcher object according different rules.
144
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
145
+		$order = OrderObjectFactory::getInstance()->getOrder();
146
+
147
+		// Fetch objects via the Content Service.
148
+		$contentService = $this->getContentService()->findBy($matcher, $order);
149
+
150
+		// Get the real field that is going to be updated.
151
+		$updatedFieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
152
+
153
+		// Get result object for storing data along the processing.
154
+		$result = $this->getJsonResult();
155
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
156
+
157
+		foreach ($contentService->getObjects() as $index => $object) {
158
+
159
+			$identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid', $language);
160
+
161
+			// It could be the identifier is not found because the translation
162
+			// of the record does not yet exist when mass-editing
163
+			if ((int)$identifier <= 0) {
164
+				continue;
165
+			}
166
+
167
+			$dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
168
+
169
+			$signalResult = $this->emitProcessContentDataSignal($object, $fieldNameAndPath, $content, $index + 1, $savingBehavior, $language);
170
+			$contentData = $signalResult->getContentData();
171
+
172
+			// Add identifier to content data, required by TCEMain.
173
+			$contentData['uid'] = $identifier;
174
+
175
+			/** @var Content $dataObject */
176
+			$dataObject = GeneralUtility::makeInstance(Content::class, $dataType, $contentData);
177
+
178
+			// Properly update object.
179
+			ContentRepositoryFactory::getInstance($dataType)->update($dataObject);
180
+
181
+			// Get the possible error messages and store them.
182
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
183
+			$result->addErrorMessages($errorMessages);
184
+
185
+			// We only want to see the detail result if there is one object updated.
186
+			// Required for inline editing + it will display some useful info on the GUI in the flash messages.
187
+			if ($contentService->getNumberOfObjects() === 1) {
188
+
189
+				// Fetch the updated object from repository.
190
+				$updatedObject = ContentRepositoryFactory::getInstance()->findByUid($object->getUid());
191
+
192
+				// Re-fetch the updated result.
193
+				$updatedResult = $this->getContentObjectResolver()->getValue($updatedObject, $fieldNameAndPath, $updatedFieldName, $language);
194
+				if (is_array($updatedResult)) {
195
+					$_updatedResult = []; // reset result set.
196
+
197
+					/** @var Content $contentObject */
198
+					foreach ($updatedResult as $contentObject) {
199
+						$labelField = Tca::table($contentObject)->getLabelField();
200
+						$values = array(
201
+							'uid' => $contentObject->getUid(),
202
+							'name' => $contentObject[$labelField],
203
+						);
204
+						$_updatedResult[] = $values;
205
+					}
206
+
207
+					$updatedResult = $_updatedResult;
208
+				}
209
+
210
+				$labelField = Tca::table($object)->getLabelField();
211
+
212
+				$processedObjectData = array(
213
+					'uid' => $object->getUid(),
214
+					'name' => $object[$labelField],
215
+					'updatedField' => $fieldNameAndPath,
216
+					'updatedValue' => $updatedResult,
217
+				);
218
+				$result->setProcessedObject($processedObjectData);
219
+
220
+				if (!empty($columns)) {
221
+					/** @var Row $row */
222
+					$row = GeneralUtility::makeInstance(\Fab\Vidi\View\Grid\Row::class, $columns);
223
+					$result->setRow($row->render($updatedObject));
224
+				}
225
+			}
226
+		}
227
+
228
+		// Set the result and render the JSON view.
229
+		$this->getJsonView()->setResult($result);
230
+		return $this->getJsonView()->render();
231
+	}
232
+
233
+	/**
234
+	 * Set the sorting of a record giving the previous object.
235
+	 *
236
+	 * @param array $matches
237
+	 * @param int $previousIdentifier
238
+	 * @return string
239
+	 */
240
+	public function sortAction(array $matches = [], $previousIdentifier = null)
241
+	{
242
+
243
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
244
+
245
+		// Fetch objects via the Content Service.
246
+		$contentService = $this->getContentService()->findBy($matcher);
247
+
248
+		// Compute the label field name of the table.
249
+		$tableTitleField = Tca::table()->getLabelField();
250
+
251
+		// Get result object for storing data along the processing.
252
+		$result = $this->getJsonResult();
253
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
254
+
255
+		foreach ($contentService->getObjects() as $object) {
256
+
257
+			// Store the first object, so that the "action" message can be more explicit when deleting only one record.
258
+			if ($contentService->getNumberOfObjects() === 1) {
259
+				$tableTitleValue = $object[$tableTitleField];
260
+				$processedObjectData = array(
261
+					'uid' => $object->getUid(),
262
+					'name' => $tableTitleValue,
263
+				);
264
+				$result->setProcessedObject($processedObjectData);
265
+			}
266
+
267
+			// The $target corresponds to the pid to move the records to.
268
+			// It can also be a negative value in case of sorting. The negative value would be the uid of its predecessor.
269
+			$target = is_null($previousIdentifier) ? $object->getPid() : (-(int)$previousIdentifier);
270
+
271
+			// Work out the object.
272
+			ContentRepositoryFactory::getInstance()->move($object, $target);
273
+
274
+			// Get the possible error messages and store them.
275
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
276
+			$result->addErrorMessages($errorMessages);
277
+		}
278
+
279
+		// Set the result and render the JSON view.
280
+		$this->getJsonView()->setResult($result);
281
+		return $this->getJsonView()->render();
282
+	}
283
+
284
+	/**
285
+	 * Returns an editing form for a given field name of a Content object.
286
+	 * Argument $fieldNameAndPath corresponds to the field name to be edited.
287
+	 * Important to notice it can contains a path, e.g. metadata.title and therefore must be analysed.
288
+	 *
289
+	 * Possible values for $matches, refer to method "updateAction".
290
+	 *
291
+	 * @param string $fieldNameAndPath
292
+	 * @param array $matches
293
+	 * @param bool $hasRecursiveSelection
294
+	 * @throws \Exception
295
+	 */
296
+	public function editAction($fieldNameAndPath, array $matches = [], $hasRecursiveSelection = false)
297
+	{
298
+
299
+		// Instantiate the Matcher object according different rules.
300
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
301
+
302
+		// Fetch objects via the Content Service.
303
+		$contentService = $this->getContentService()->findBy($matcher);
304
+
305
+		$dataType = $this->getFieldPathResolver()->getDataType($fieldNameAndPath);
306
+		$fieldName = $this->getFieldPathResolver()->stripFieldPath($fieldNameAndPath);
307
+
308
+		$fieldType = Tca::table($dataType)->field($fieldName)->getType();
309
+		$this->view->assign('fieldType', ucfirst($fieldType));
310
+		$this->view->assign('dataType', $dataType);
311
+		$this->view->assign('fieldName', $fieldName);
312
+		$this->view->assign('matches', $matches);
313
+		$this->view->assign('fieldNameAndPath', $fieldNameAndPath);
314
+		$this->view->assign('numberOfObjects', $contentService->getNumberOfObjects());
315
+		$this->view->assign('hasRecursiveSelection', $hasRecursiveSelection);
316
+		$this->view->assign('editWholeSelection', empty($matches['uid'])); // necessary??
317
+
318
+		// Fetch content and its relations.
319
+		if ($fieldType === FieldType::MULTISELECT) {
320
+
321
+			$object = ContentRepositoryFactory::getInstance()->findOneBy($matcher);
322
+			$identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid');
323
+			$dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
324
+
325
+			$content = ContentRepositoryFactory::getInstance($dataType)->findByUid($identifier);
326
+
327
+			// Makes sure the object was retrieved. Security!
328
+			if (!$content) {
329
+				$message = sprintf('I could not retrieved content object of type "%s" with identifier %s.', $dataType, $identifier);
330
+				throw new \Exception($message, 1402350182);
331
+			}
332
+
333
+			$relatedDataType = Tca::table($dataType)->field($fieldName)->getForeignTable();
334
+
335
+			// Initialize the matcher object.
336
+			/** @var Matcher $matcher */
337
+			$matcher = GeneralUtility::makeInstance(Matcher::class, [], $relatedDataType);
338
+
339
+			// Default ordering for related data type.
340
+			$defaultOrderings = Tca::table($relatedDataType)->getDefaultOrderings();
341
+			/** @var Order $order */
342
+			$defaultOrder = GeneralUtility::makeInstance(Order::class, $defaultOrderings);
343
+
344
+			// Fetch related contents
345
+			$relatedContents = ContentRepositoryFactory::getInstance($relatedDataType)->findBy($matcher, $defaultOrder);
346
+
347
+			if (Tca::table($dataType)->field($fieldName)->isRenderModeTree()) {
348
+
349
+				$fieldConfiguration = Tca::table($dataType)->field($fieldName)->getConfiguration();
350
+				$parentField = $fieldConfiguration['treeConfig']['parentField'];
351
+
352
+				$flatTree = [];
353
+				foreach ($relatedContents as $node) {
354
+					$flatTree[$node->getUid()] = array(
355
+						'item' => $node,
356
+						'parent' => $node[$parentField] ? $node[$parentField]['uid'] : null,
357
+					);
358
+				}
359
+
360
+				$tree = [];
361
+
362
+				// If leaves are selected without its parents selected, those are shown as parent
363
+				foreach ($flatTree as $id => &$flatNode) {
364
+					if (!isset($flatTree[$flatNode['parent']])) {
365
+						$flatNode['parent'] = null;
366
+					}
367
+				}
368
+
369
+				foreach ($flatTree as $id => &$node) {
370
+					if ($node['parent'] === null) {
371
+						$tree[$id] = &$node;
372
+					} else {
373
+						$flatTree[$node['parent']]['children'][$id] = &$node;
374
+					}
375
+				}
376
+
377
+				$relatedContents = $tree;
378
+			}
379
+
380
+			$this->view->assign('content', $content);
381
+			$this->view->assign('relatedContents', $relatedContents);
382
+			$this->view->assign('relatedDataType', $relatedDataType);
383
+			$this->view->assign('relatedContentTitle', Tca::table($relatedDataType)->getTitle());
384
+			$this->view->assign(
385
+				'renderMode',
386
+				Tca::table($dataType)->field($fieldName)->isRenderModeTree() ? FieldType::TREE : null
387
+			);
388
+		}
389
+	}
390
+
391
+	/**
392
+	 * Retrieve Content objects first according to matching criteria and then "delete" them.
393
+	 *
394
+	 * Possible values for $matches, refer to method "updateAction".
395
+	 *
396
+	 * @param array $matches
397
+	 * @return string
398
+	 */
399
+	public function deleteAction(array $matches = [])
400
+	{
401
+
402
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
403
+
404
+		// Fetch objects via the Content Service.
405
+		$contentService = $this->getContentService()->findBy($matcher);
406
+
407
+		// Compute the label field name of the table.
408
+		$tableTitleField = Tca::table()->getLabelField();
409
+
410
+		// Get result object for storing data along the processing.
411
+		$result = $this->getJsonResult();
412
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
413
+
414
+		foreach ($contentService->getObjects() as $object) {
415
+
416
+			// Store the first object, so that the delete message can be more explicit when deleting only one record.
417
+			if ($contentService->getNumberOfObjects() === 1) {
418
+				$tableTitleValue = $object[$tableTitleField];
419
+				$processedObjectData = array(
420
+					'uid' => $object->getUid(),
421
+					'name' => $tableTitleValue,
422
+				);
423
+				$result->setProcessedObject($processedObjectData);
424
+			}
425
+
426
+			// Properly delete object.
427
+			ContentRepositoryFactory::getInstance()->remove($object);
428
+
429
+			// Get the possible error messages and store them.
430
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
431
+			$result->addErrorMessages($errorMessages);
432
+		}
433
+
434
+		// Set the result and render the JSON view.
435
+		$this->getJsonView()->setResult($result);
436
+		return $this->getJsonView()->render();
437
+	}
438
+
439
+	/**
440
+	 * Retrieve Content objects first according to matching criteria and then "copy" them.
441
+	 *
442
+	 * Possible values for $matches, refer to method "updateAction".
443
+	 *
444
+	 * @param string $target
445
+	 * @param array $matches
446
+	 * @throws \Exception
447
+	 * @return string
448
+	 */
449
+	public function copyAction($target, array $matches = [])
450
+	{
451
+		// @todo
452
+		throw new \Exception('Not yet implemented', 1410192546);
453
+	}
454
+
455
+	/**
456
+	 * Retrieve Content objects from the Clipboard then "copy" them according to the target.
457
+	 *
458
+	 * @param string $target
459
+	 * @throws \Exception
460
+	 * @return string
461
+	 */
462
+	public function copyClipboardAction($target)
463
+	{
464
+
465
+		// Retrieve matcher object from clipboard.
466
+		$matcher = $this->getClipboardService()->getMatcher();
467
+
468
+		// Fetch objects via the Content Service.
469
+		$contentService = $this->getContentService()->findBy($matcher);
470
+
471
+		// Compute the label field name of the table.
472
+		$tableTitleField = Tca::table()->getLabelField();
473
+
474
+		// Get result object for storing data along the processing.
475
+		$result = $this->getJsonResult();
476
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
477
+
478
+		foreach ($contentService->getObjects() as $object) {
479
+
480
+			// Store the first object, so that the "action" message can be more explicit when deleting only one record.
481
+			if ($contentService->getNumberOfObjects() === 1) {
482
+				$tableTitleValue = $object[$tableTitleField];
483
+				$processedObjectData = array(
484
+					'uid' => $object->getUid(),
485
+					'name' => $tableTitleValue,
486
+				);
487
+				$result->setProcessedObject($processedObjectData);
488
+			}
489
+
490
+			// Work out the object.
491
+			ContentRepositoryFactory::getInstance()->copy($object, $target);
492
+
493
+			// Get the possible error messages and store them.
494
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
495
+			$result->addErrorMessages($errorMessages);
496
+		}
497
+
498
+		// Flush Clipboard if told so.
499
+		if (GeneralUtility::_GP('flushClipboard')) {
500
+			$this->getClipboardService()->flush();
501
+		}
502
+
503
+		// Set the result and render the JSON view.
504
+		$this->getJsonView()->setResult($result);
505
+		return $this->getJsonView()->render();
506
+	}
507
+
508
+	/**
509
+	 * Retrieve Content objects first according to matching criteria and then "move" them.
510
+	 *
511
+	 * Possible values for $matches, refer to method "updateAction".
512
+	 *
513
+	 * @param string $target
514
+	 * @param array $matches
515
+	 * @return string
516
+	 */
517
+	public function moveAction($target, array $matches = [])
518
+	{
519
+
520
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
521
+
522
+		// Fetch objects via the Content Service.
523
+		$contentService = $this->getContentService()->findBy($matcher);
524
+
525
+		// Compute the label field name of the table.
526
+		$tableTitleField = Tca::table()->getLabelField();
527
+
528
+		// Get result object for storing data along the processing.
529
+		$result = $this->getJsonResult();
530
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
531
+
532
+		foreach ($contentService->getObjects() as $object) {
533
+
534
+			// Store the first object, so that the "action" message can be more explicit when deleting only one record.
535
+			if ($contentService->getNumberOfObjects() === 1) {
536
+				$tableTitleValue = $object[$tableTitleField];
537
+				$processedObjectData = array(
538
+					'uid' => $object->getUid(),
539
+					'name' => $tableTitleValue,
540
+				);
541
+				$result->setProcessedObject($processedObjectData);
542
+			}
543
+
544
+			// Work out the object.
545
+			ContentRepositoryFactory::getInstance()->move($object, $target);
546
+
547
+			// Get the possible error messages and store them.
548
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
549
+			$result->addErrorMessages($errorMessages);
550
+		}
551
+
552
+		// Set the result and render the JSON view.
553
+		$this->getJsonView()->setResult($result);
554
+		return $this->getJsonView()->render();
555
+	}
556
+
557
+	/**
558
+	 * Retrieve Content objects from the Clipboard then "move" them according to the target.
559
+	 *
560
+	 * @param string $target
561
+	 * @return string
562
+	 */
563
+	public function moveClipboardAction($target)
564
+	{
565
+
566
+		// Retrieve matcher object from clipboard.
567
+		$matcher = $this->getClipboardService()->getMatcher();
568
+
569
+		// Fetch objects via the Content Service.
570
+		$contentService = $this->getContentService()->findBy($matcher);
571
+
572
+		// Compute the label field name of the table.
573
+		$tableTitleField = Tca::table()->getLabelField();
574
+
575
+		// Get result object for storing data along the processing.
576
+		$result = $this->getJsonResult();
577
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
578
+
579
+		foreach ($contentService->getObjects() as $object) {
580
+
581
+			// Store the first object, so that the "action" message can be more explicit when deleting only one record.
582
+			if ($contentService->getNumberOfObjects() === 1) {
583
+				$tableTitleValue = $object[$tableTitleField];
584
+				$processedObjectData = array(
585
+					'uid' => $object->getUid(),
586
+					'name' => $tableTitleValue,
587
+				);
588
+				$result->setProcessedObject($processedObjectData);
589
+			}
590
+
591
+			// Work out the object.
592
+			ContentRepositoryFactory::getInstance()->move($object, $target);
593
+
594
+			// Get the possible error messages and store them.
595
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
596
+			$result->addErrorMessages($errorMessages);
597
+		}
598
+
599
+		// Flush Clipboard if told so.
600
+		if (GeneralUtility::_GP('flushClipboard')) {
601
+			$this->getClipboardService()->flush();
602
+		}
603
+
604
+		// Set the result and render the JSON view.
605
+		$this->getJsonView()->setResult($result);
606
+		return $this->getJsonView()->render();
607
+	}
608
+
609
+	/**
610
+	 * Retrieve Content objects first according to matching criteria and then "localize" them.
611
+	 *
612
+	 * Possible values for $matches, refer to method "updateAction".
613
+	 *
614
+	 * @param string $fieldNameAndPath
615
+	 * @param array $matches
616
+	 * @param int $language
617
+	 * @return string
618
+	 * @throws \Exception
619
+	 */
620
+	public function localizeAction($fieldNameAndPath, array $matches = [], $language = 0)
621
+	{
622
+
623
+		$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches);
624
+
625
+		// Fetch objects via the Content Service.
626
+		$contentService = $this->getContentService()->findBy($matcher);
627
+
628
+		// Get result object for storing data along the processing.
629
+		$result = $this->getJsonResult();
630
+		$result->setNumberOfObjects($contentService->getNumberOfObjects());
631
+
632
+		foreach ($contentService->getObjects() as $object) {
633
+
634
+			$identifier = $this->getContentObjectResolver()->getValue($object, $fieldNameAndPath, 'uid');
635
+			$dataType = $this->getContentObjectResolver()->getDataType($object, $fieldNameAndPath);
636
+
637
+			// Fetch the source object to be localized.
638
+			/** @var Content $content */
639
+			$content = ContentRepositoryFactory::getInstance($dataType)->findByIdentifier($identifier);
640
+
641
+			// Makes sure the object was retrieved. Security!
642
+			if (!$content) {
643
+				$message = sprintf('Something went wrong when retrieving content "%s" with identifier "%s".', $dataType, $identifier);
644
+				throw new \Exception($message, 1412343097);
645
+			}
646
+
647
+			// Handover the localization to the Repository.
648
+			ContentRepositoryFactory::getInstance($dataType)->localize($content, $language);
649
+
650
+			// Get the possible error messages and store them.
651
+			$errorMessages = ContentRepositoryFactory::getInstance()->getErrorMessages();
652
+
653
+			// Redirect to TCEForm so that the BE User can do its job!
654
+			if ($contentService->getNumberOfObjects() === 1) {
655
+
656
+				if (!empty($errorMessages)) {
657
+					$message = sprintf('Something went wrong when localizing content "%s" with identifier "%s". <br/>%s',
658
+						$dataType,
659
+						$identifier,
660
+						implode('<br/>', $errorMessages)
661
+					);
662
+					throw new \Exception($message, 1412343098);
663
+				}
664
+
665
+				$localizedContent = $this->getLanguageService()->getLocalizedContent($content, $language);
666
+				if (empty($localizedContent)) {
667
+					$message = sprintf('Oups! I could not retrieve localized content of type "%s" with identifier "%s"',
668
+						$content->getDataType(),
669
+						$content->getUid()
670
+					);
671
+					throw new \Exception($message, 1412343099);
672
+				}
673
+
674
+				/** @var EditUri $uri */
675
+				$uriRenderer = GeneralUtility::makeInstance(EditUri::class);
676
+				$uri = $uriRenderer->render($localizedContent);
677
+				HttpUtility::redirect($uri);
678
+				break; // no need to further continue
679
+			}
680
+
681
+			$result->addErrorMessages($errorMessages);
682
+		}
683
+
684
+		// Set the result and render the JSON view.
685
+		$this->getJsonView()->setResult($result);
686
+		return $this->getJsonView()->render();
687
+	}
688
+
689
+	/**
690
+	 * Get the Vidi Module Loader.
691
+	 *
692
+	 * @return ContentService
693
+	 */
694
+	protected function getContentService()
695
+	{
696
+		return GeneralUtility::makeInstance(ContentService::class);
697
+	}
698
+
699
+	/**
700
+	 * @return ContentObjectResolver
701
+	 */
702
+	protected function getContentObjectResolver()
703
+	{
704
+		return GeneralUtility::makeInstance(ContentObjectResolver::class);
705
+	}
706
+
707
+	/**
708
+	 * @return FieldPathResolver
709
+	 */
710
+	protected function getFieldPathResolver()
711
+	{
712
+		return GeneralUtility::makeInstance(FieldPathResolver::class);
713
+	}
714
+
715
+	/**
716
+	 * Return a special view for handling JSON
717
+	 * Goal is to have this view injected but require more configuration.
718
+	 *
719
+	 * @return JsonView
720
+	 */
721
+	protected function getJsonView()
722
+	{
723
+		if (!$this->view instanceof JsonView) {
724
+			/** @var JsonView $view */
725
+			$this->view = $this->objectManager->get(JsonView::class);
726
+			$this->view->setResponse($this->response);
727
+		}
728
+		return $this->view;
729
+	}
730
+
731
+	/**
732
+	 * @return JsonResult|object
733
+	 */
734
+	protected function getJsonResult()
735
+	{
736
+		return GeneralUtility::makeInstance(JsonResult::class);
737
+	}
738
+
739
+	/**
740
+	 * Signal that is called for post-processing content data send to the server for update.
741
+	 *
742
+	 * @param Content $contentObject
743
+	 * @param $fieldNameAndPath
744
+	 * @param $contentData
745
+	 * @param $counter
746
+	 * @param $savingBehavior
747
+	 * @param $language
748
+	 * @return ProcessContentDataSignalArguments
749
+	 */
750
+	protected function emitProcessContentDataSignal(Content $contentObject, $fieldNameAndPath, $contentData, $counter, $savingBehavior, $language)
751
+	{
752
+
753
+		/** @var \Fab\Vidi\Signal\ProcessContentDataSignalArguments $signalArguments */
754
+		$signalArguments = GeneralUtility::makeInstance(\Fab\Vidi\Signal\ProcessContentDataSignalArguments::class);
755
+		$signalArguments->setContentObject($contentObject)
756
+			->setFieldNameAndPath($fieldNameAndPath)
757
+			->setContentData($contentData)
758
+			->setCounter($counter)
759
+			->setSavingBehavior($savingBehavior)
760
+			->setLanguage($language);
761
+
762
+		$signalResult = $this->getSignalSlotDispatcher()->dispatch('Fab\Vidi\Controller\Backend\ContentController', 'processContentData', array($signalArguments));
763
+		return $signalResult[0];
764
+	}
765
+
766
+	/**
767
+	 * Get the SignalSlot dispatcher.
768
+	 *
769
+	 * @return Dispatcher
770
+	 */
771
+	protected function getSignalSlotDispatcher()
772
+	{
773
+		return $this->objectManager->get(Dispatcher::class);
774
+	}
775
+
776
+	/**
777
+	 * Get the Clipboard service.
778
+	 *
779
+	 * @return ClipboardService
780
+	 */
781
+	protected function getClipboardService()
782
+	{
783
+		return GeneralUtility::makeInstance(ClipboardService::class);
784
+	}
785
+
786
+	/**
787
+	 * @return LanguageService
788
+	 */
789
+	protected function getLanguageService()
790
+	{
791
+		return GeneralUtility::makeInstance(LanguageService::class);
792
+	}
793
+
794
+	/**
795
+	 * Get the Vidi Module Loader.
796
+	 *
797
+	 * @return ModuleLoader
798
+	 */
799
+	protected function getModuleLoader()
800
+	{
801
+		return GeneralUtility::makeInstance(ModuleLoader::class);
802
+	}
803 803
 
804 804
 }
Please login to merge, or discard this patch.
Classes/Database/DatabaseConnection.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
      * Use this to execute database queries instead of directly calling $this->link->query()
474 474
      *
475 475
      * @param string $query The query to send to the database
476
-     * @return bool|\mysqli_result
476
+     * @return string
477 477
      */
478 478
     protected function query($query)
479 479
     {
@@ -832,7 +832,7 @@  discard block
 block discarded – undo
832 832
      *
833 833
      * @param string $query The query to execute
834 834
      * @param array $queryComponents The components of the query to execute
835
-     * @return \mysqli_stmt|object MySQLi statement / DBAL object
835
+     * @return \mysqli_stmt|null MySQLi statement / DBAL object
836 836
      * @internal This method may only be called by \Fab\Vidi\Database\PreparedStatement
837 837
      */
838 838
     public function prepare_PREPAREDquery($query, array $queryComponents)
@@ -1983,7 +1983,7 @@  discard block
 block discarded – undo
1983 1983
     /**
1984 1984
      * Serialize destructs current connection
1985 1985
      *
1986
-     * @return array All protected properties that should be saved
1986
+     * @return string[] All protected properties that should be saved
1987 1987
      */
1988 1988
     public function __sleep()
1989 1989
     {
Please login to merge, or discard this patch.
Indentation   +1921 added lines, -1921 removed lines patch added patch discarded remove patch
@@ -47,146 +47,146 @@  discard block
 block discarded – undo
47 47
  */
48 48
 class DatabaseConnection
49 49
 {
50
-    /**
51
-     * The AND constraint in where clause
52
-     *
53
-     * @var string
54
-     */
55
-    const AND_Constraint = 'AND';
56
-
57
-    /**
58
-     * The OR constraint in where clause
59
-     *
60
-     * @var string
61
-     */
62
-    const OR_Constraint = 'OR';
63
-
64
-    /**
65
-     * Set "TRUE" or "1" if you want database errors outputted. Set to "2" if you also want successful database actions outputted.
66
-     *
67
-     * @var bool|int
68
-     */
69
-    public $debugOutput = false;
70
-
71
-    /**
72
-     * Internally: Set to last built query (not necessarily executed...)
73
-     *
74
-     * @var string
75
-     */
76
-    public $debug_lastBuiltQuery = '';
77
-
78
-    /**
79
-     * Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
80
-     *
81
-     * @var bool
82
-     */
83
-    public $store_lastBuiltQuery = false;
84
-
85
-    /**
86
-     * Set this to 1 to get queries explained (devIPmask must match). Set the value to 2 to the same but disregarding the devIPmask.
87
-     * There is an alternative option to enable explain output in the admin panel under "TypoScript", which will produce much nicer output, but only works in FE.
88
-     *
89
-     * @var bool
90
-     */
91
-    public $explainOutput = 0;
92
-
93
-    /**
94
-     * @var string Database host to connect to
95
-     */
96
-    protected $databaseHost = '';
97
-
98
-    /**
99
-     * @var int Database port to connect to
100
-     */
101
-    protected $databasePort = 3306;
102
-
103
-    /**
104
-     * @var string|NULL Database socket to connect to
105
-     */
106
-    protected $databaseSocket = null;
107
-
108
-    /**
109
-     * @var string Database name to connect to
110
-     */
111
-    protected $databaseName = '';
112
-
113
-    /**
114
-     * @var string Database user to connect with
115
-     */
116
-    protected $databaseUsername = '';
117
-
118
-    /**
119
-     * @var string Database password to connect with
120
-     */
121
-    protected $databaseUserPassword = '';
122
-
123
-    /**
124
-     * @var bool TRUE if database connection should be persistent
125
-     * @see http://php.net/manual/de/mysqli.persistconns.php
126
-     */
127
-    protected $persistentDatabaseConnection = false;
128
-
129
-    /**
130
-     * @var bool TRUE if connection between client and sql server is compressed
131
-     */
132
-    protected $connectionCompression = false;
133
-
134
-    /**
135
-     * The charset for the connection; will be passed on to
136
-     * mysqli_set_charset during connection initialization.
137
-     *
138
-     * @var string
139
-     */
140
-    protected $connectionCharset = 'utf8';
141
-
142
-    /**
143
-     * @var array List of commands executed after connection was established
144
-     */
145
-    protected $initializeCommandsAfterConnect = [];
146
-
147
-    /**
148
-     * @var bool TRUE if database connection is established
149
-     */
150
-    protected $isConnected = false;
151
-
152
-    /**
153
-     * @var \mysqli $link Default database link object
154
-     */
155
-    protected $link = null;
156
-
157
-    /**
158
-     * Default character set, applies unless character set or collation are explicitly set
159
-     *
160
-     * @var string
161
-     */
162
-    public $default_charset = 'utf8';
163
-
164
-    /**
165
-     * @var array<PostProcessQueryHookInterface>
166
-     */
167
-    protected $preProcessHookObjects = [];
168
-
169
-    /**
170
-     * @var array<PreProcessQueryHookInterface>
171
-     */
172
-    protected $postProcessHookObjects = [];
173
-
174
-    /**
175
-     * Internal property to mark if a deprecation log warning has been thrown in this request
176
-     * in order to avoid a load of deprecation.
177
-     * @var bool
178
-     */
179
-    protected $deprecationWarningThrown = false;
180
-
181
-    /**
182
-     * Initialize the database connection
183
-     */
184
-    public function initialize()
185
-    {
186
-        // Intentionally blank as this will be overloaded by DBAL
187
-    }
188
-
189
-    /************************************
50
+	/**
51
+	 * The AND constraint in where clause
52
+	 *
53
+	 * @var string
54
+	 */
55
+	const AND_Constraint = 'AND';
56
+
57
+	/**
58
+	 * The OR constraint in where clause
59
+	 *
60
+	 * @var string
61
+	 */
62
+	const OR_Constraint = 'OR';
63
+
64
+	/**
65
+	 * Set "TRUE" or "1" if you want database errors outputted. Set to "2" if you also want successful database actions outputted.
66
+	 *
67
+	 * @var bool|int
68
+	 */
69
+	public $debugOutput = false;
70
+
71
+	/**
72
+	 * Internally: Set to last built query (not necessarily executed...)
73
+	 *
74
+	 * @var string
75
+	 */
76
+	public $debug_lastBuiltQuery = '';
77
+
78
+	/**
79
+	 * Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
80
+	 *
81
+	 * @var bool
82
+	 */
83
+	public $store_lastBuiltQuery = false;
84
+
85
+	/**
86
+	 * Set this to 1 to get queries explained (devIPmask must match). Set the value to 2 to the same but disregarding the devIPmask.
87
+	 * There is an alternative option to enable explain output in the admin panel under "TypoScript", which will produce much nicer output, but only works in FE.
88
+	 *
89
+	 * @var bool
90
+	 */
91
+	public $explainOutput = 0;
92
+
93
+	/**
94
+	 * @var string Database host to connect to
95
+	 */
96
+	protected $databaseHost = '';
97
+
98
+	/**
99
+	 * @var int Database port to connect to
100
+	 */
101
+	protected $databasePort = 3306;
102
+
103
+	/**
104
+	 * @var string|NULL Database socket to connect to
105
+	 */
106
+	protected $databaseSocket = null;
107
+
108
+	/**
109
+	 * @var string Database name to connect to
110
+	 */
111
+	protected $databaseName = '';
112
+
113
+	/**
114
+	 * @var string Database user to connect with
115
+	 */
116
+	protected $databaseUsername = '';
117
+
118
+	/**
119
+	 * @var string Database password to connect with
120
+	 */
121
+	protected $databaseUserPassword = '';
122
+
123
+	/**
124
+	 * @var bool TRUE if database connection should be persistent
125
+	 * @see http://php.net/manual/de/mysqli.persistconns.php
126
+	 */
127
+	protected $persistentDatabaseConnection = false;
128
+
129
+	/**
130
+	 * @var bool TRUE if connection between client and sql server is compressed
131
+	 */
132
+	protected $connectionCompression = false;
133
+
134
+	/**
135
+	 * The charset for the connection; will be passed on to
136
+	 * mysqli_set_charset during connection initialization.
137
+	 *
138
+	 * @var string
139
+	 */
140
+	protected $connectionCharset = 'utf8';
141
+
142
+	/**
143
+	 * @var array List of commands executed after connection was established
144
+	 */
145
+	protected $initializeCommandsAfterConnect = [];
146
+
147
+	/**
148
+	 * @var bool TRUE if database connection is established
149
+	 */
150
+	protected $isConnected = false;
151
+
152
+	/**
153
+	 * @var \mysqli $link Default database link object
154
+	 */
155
+	protected $link = null;
156
+
157
+	/**
158
+	 * Default character set, applies unless character set or collation are explicitly set
159
+	 *
160
+	 * @var string
161
+	 */
162
+	public $default_charset = 'utf8';
163
+
164
+	/**
165
+	 * @var array<PostProcessQueryHookInterface>
166
+	 */
167
+	protected $preProcessHookObjects = [];
168
+
169
+	/**
170
+	 * @var array<PreProcessQueryHookInterface>
171
+	 */
172
+	protected $postProcessHookObjects = [];
173
+
174
+	/**
175
+	 * Internal property to mark if a deprecation log warning has been thrown in this request
176
+	 * in order to avoid a load of deprecation.
177
+	 * @var bool
178
+	 */
179
+	protected $deprecationWarningThrown = false;
180
+
181
+	/**
182
+	 * Initialize the database connection
183
+	 */
184
+	public function initialize()
185
+	{
186
+		// Intentionally blank as this will be overloaded by DBAL
187
+	}
188
+
189
+	/************************************
190 190
      *
191 191
      * Query execution
192 192
      *
@@ -199,657 +199,657 @@  discard block
 block discarded – undo
199 199
      *
200 200
      **************************************/
201 201
 
202
-    /**
203
-     * Creates and executes an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
204
-     * Using this function specifically allows us to handle BLOB and CLOB fields depending on DB
205
-     *
206
-     * @param string $table Table name
207
-     * @param array $fields_values Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$insertFields" with 'fieldname'=>'value' and pass it to this function as argument.
208
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
209
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
210
-     */
211
-    public function exec_INSERTquery($table, $fields_values, $no_quote_fields = false)
212
-    {
213
-        $this->logDeprecation();
214
-        $res = $this->query($this->INSERTquery($table, $fields_values, $no_quote_fields));
215
-        if ($this->debugOutput) {
216
-            $this->debug('exec_INSERTquery');
217
-        }
218
-        foreach ($this->postProcessHookObjects as $hookObject) {
219
-            /** @var $hookObject PostProcessQueryHookInterface */
220
-            $hookObject->exec_INSERTquery_postProcessAction($table, $fields_values, $no_quote_fields, $this);
221
-        }
222
-        return $res;
223
-    }
224
-
225
-    /**
226
-     * Creates and executes an INSERT SQL-statement for $table with multiple rows.
227
-     *
228
-     * @param string $table Table name
229
-     * @param array $fields Field names
230
-     * @param array $rows Table rows. Each row should be an array with field values mapping to $fields
231
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
232
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
233
-     */
234
-    public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = false)
235
-    {
236
-        $this->logDeprecation();
237
-        $res = $this->query($this->INSERTmultipleRows($table, $fields, $rows, $no_quote_fields));
238
-        if ($this->debugOutput) {
239
-            $this->debug('exec_INSERTmultipleRows');
240
-        }
241
-        foreach ($this->postProcessHookObjects as $hookObject) {
242
-            /** @var $hookObject PostProcessQueryHookInterface */
243
-            $hookObject->exec_INSERTmultipleRows_postProcessAction($table, $fields, $rows, $no_quote_fields, $this);
244
-        }
245
-        return $res;
246
-    }
247
-
248
-    /**
249
-     * Creates and executes an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
250
-     * Using this function specifically allow us to handle BLOB and CLOB fields depending on DB
251
-     *
252
-     * @param string $table Database tablename
253
-     * @param string $where WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
254
-     * @param array $fields_values Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
255
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
256
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
257
-     */
258
-    public function exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields = false)
259
-    {
260
-        $this->logDeprecation();
261
-        $res = $this->query($this->UPDATEquery($table, $where, $fields_values, $no_quote_fields));
262
-        if ($this->debugOutput) {
263
-            $this->debug('exec_UPDATEquery');
264
-        }
265
-        foreach ($this->postProcessHookObjects as $hookObject) {
266
-            /** @var $hookObject PostProcessQueryHookInterface */
267
-            $hookObject->exec_UPDATEquery_postProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
268
-        }
269
-        return $res;
270
-    }
271
-
272
-    /**
273
-     * Creates and executes a DELETE SQL-statement for $table where $where-clause
274
-     *
275
-     * @param string $table Database tablename
276
-     * @param string $where WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
277
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
278
-     */
279
-    public function exec_DELETEquery($table, $where)
280
-    {
281
-        $this->logDeprecation();
282
-        $res = $this->query($this->DELETEquery($table, $where));
283
-        if ($this->debugOutput) {
284
-            $this->debug('exec_DELETEquery');
285
-        }
286
-        foreach ($this->postProcessHookObjects as $hookObject) {
287
-            /** @var $hookObject PostProcessQueryHookInterface */
288
-            $hookObject->exec_DELETEquery_postProcessAction($table, $where, $this);
289
-        }
290
-        return $res;
291
-    }
292
-
293
-    /**
294
-     * Creates and executes a SELECT SQL-statement
295
-     * Using this function specifically allow us to handle the LIMIT feature independently of DB.
296
-     *
297
-     * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
298
-     * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
299
-     * @param string $where_clause Additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
300
-     * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
301
-     * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
302
-     * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
303
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
304
-     */
305
-    public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
306
-    {
307
-        $this->logDeprecation();
308
-        $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
309
-        $res = $this->query($query);
310
-        if ($this->debugOutput) {
311
-            $this->debug('exec_SELECTquery');
312
-        }
313
-        if ($this->explainOutput) {
314
-            $this->explain($query, $from_table, $res->num_rows);
315
-        }
316
-        foreach ($this->postProcessHookObjects as $hookObject) {
317
-            /** @var $hookObject PostProcessQueryHookInterface */
318
-            $hookObject->exec_SELECTquery_postProcessAction($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $this);
319
-        }
320
-        return $res;
321
-    }
322
-
323
-    /**
324
-     * Creates and executes a SELECT query, selecting fields ($select) from two/three tables joined
325
-     * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
326
-     * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
327
-     * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
328
-     *
329
-     * @param string $select Field list for SELECT
330
-     * @param string $local_table Tablename, local table
331
-     * @param string $mm_table Tablename, relation table
332
-     * @param string $foreign_table Tablename, foreign table
333
-     * @param string $whereClause Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! You have to prepend 'AND ' to this parameter yourself!
334
-     * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
335
-     * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
336
-     * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
337
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
338
-     * @see exec_SELECTquery()
339
-     */
340
-    public function exec_SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
341
-    {
342
-        $this->logDeprecation();
343
-        $queryParts = $this->getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause, $groupBy, $orderBy, $limit);
344
-        return $this->exec_SELECT_queryArray($queryParts);
345
-    }
346
-
347
-    /**
348
-     * Executes a select based on input query parts array
349
-     *
350
-     * @param array $queryParts Query parts array
351
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
352
-     * @see exec_SELECTquery()
353
-     */
354
-    public function exec_SELECT_queryArray($queryParts)
355
-    {
356
-        $this->logDeprecation();
357
-        return $this->exec_SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT']);
358
-    }
359
-
360
-    /**
361
-     * Creates and executes a SELECT SQL-statement AND traverse result set and returns array with records in.
362
-     *
363
-     * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
364
-     * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
365
-     * @param string $where_clause Additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
366
-     * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
367
-     * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
368
-     * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
369
-     * @param string $uidIndexField If set, the result array will carry this field names value as index. Requires that field to be selected of course!
370
-     * @return array|NULL Array of rows, or NULL in case of SQL error
371
-     * @see exec_SELECTquery()
372
-     * @throws \InvalidArgumentException
373
-     */
374
-    public function exec_SELECTgetRows($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $uidIndexField = '')
375
-    {
376
-        $this->logDeprecation();
377
-        $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
378
-        if ($this->sql_error()) {
379
-            $this->sql_free_result($res);
380
-            return null;
381
-        }
382
-        $output = [];
383
-        $firstRecord = true;
384
-        while ($record = $this->sql_fetch_assoc($res)) {
385
-            if ($uidIndexField) {
386
-                if ($firstRecord) {
387
-                    $firstRecord = false;
388
-                    if (!array_key_exists($uidIndexField, $record)) {
389
-                        $this->sql_free_result($res);
390
-                        throw new \InvalidArgumentException('The given $uidIndexField "' . $uidIndexField . '" is not available in the result.', 1432933855);
391
-                    }
392
-                }
393
-                $output[$record[$uidIndexField]] = $record;
394
-            } else {
395
-                $output[] = $record;
396
-            }
397
-        }
398
-        $this->sql_free_result($res);
399
-        return $output;
400
-    }
401
-
402
-    /**
403
-     * Creates and executes a SELECT SQL-statement AND gets a result set and returns an array with a single record in.
404
-     * LIMIT is automatically set to 1 and can not be overridden.
405
-     *
406
-     * @param string $select_fields List of fields to select from the table.
407
-     * @param string $from_table Table(s) from which to select.
408
-     * @param string $where_clause Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
409
-     * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
410
-     * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
411
-     * @param bool $numIndex If set, the result will be fetched with sql_fetch_row, otherwise sql_fetch_assoc will be used.
412
-     * @return array|FALSE|NULL Single row, FALSE on empty result, NULL on error
413
-     */
414
-    public function exec_SELECTgetSingleRow($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $numIndex = false)
415
-    {
416
-        $this->logDeprecation();
417
-        $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, '1');
418
-        $output = null;
419
-        if ($res !== false) {
420
-            if ($numIndex) {
421
-                $output = $this->sql_fetch_row($res);
422
-            } else {
423
-                $output = $this->sql_fetch_assoc($res);
424
-            }
425
-            $this->sql_free_result($res);
426
-        }
427
-        return $output;
428
-    }
429
-
430
-    /**
431
-     * Counts the number of rows in a table.
432
-     *
433
-     * @param string $field Name of the field to use in the COUNT() expression (e.g. '*')
434
-     * @param string $table Name of the table to count rows for
435
-     * @param string $where (optional) WHERE statement of the query
436
-     * @return mixed Number of rows counter (int) or FALSE if something went wrong (bool)
437
-     */
438
-    public function exec_SELECTcountRows($field, $table, $where = '1=1')
439
-    {
440
-        $this->logDeprecation();
441
-        $count = false;
442
-        $resultSet = $this->exec_SELECTquery('COUNT(' . $field . ')', $table, $where);
443
-        if ($resultSet !== false) {
444
-            list($count) = $this->sql_fetch_row($resultSet);
445
-            $count = (int)$count;
446
-            $this->sql_free_result($resultSet);
447
-        }
448
-        return $count;
449
-    }
450
-
451
-    /**
452
-     * Truncates a table.
453
-     *
454
-     * @param string $table Database tablename
455
-     * @return mixed Result from handler
456
-     */
457
-    public function exec_TRUNCATEquery($table)
458
-    {
459
-        $this->logDeprecation();
460
-        $res = $this->query($this->TRUNCATEquery($table));
461
-        if ($this->debugOutput) {
462
-            $this->debug('exec_TRUNCATEquery');
463
-        }
464
-        foreach ($this->postProcessHookObjects as $hookObject) {
465
-            /** @var $hookObject PostProcessQueryHookInterface */
466
-            $hookObject->exec_TRUNCATEquery_postProcessAction($table, $this);
467
-        }
468
-        return $res;
469
-    }
470
-
471
-    /**
472
-     * Central query method. Also checks if there is a database connection.
473
-     * Use this to execute database queries instead of directly calling $this->link->query()
474
-     *
475
-     * @param string $query The query to send to the database
476
-     * @return bool|\mysqli_result
477
-     */
478
-    protected function query($query)
479
-    {
480
-        $this->logDeprecation();
481
-        if (!$this->isConnected) {
482
-            $this->connectDB();
483
-        }
484
-        return $this->link->query($query);
485
-    }
486
-
487
-    /**************************************
202
+	/**
203
+	 * Creates and executes an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
204
+	 * Using this function specifically allows us to handle BLOB and CLOB fields depending on DB
205
+	 *
206
+	 * @param string $table Table name
207
+	 * @param array $fields_values Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$insertFields" with 'fieldname'=>'value' and pass it to this function as argument.
208
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
209
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
210
+	 */
211
+	public function exec_INSERTquery($table, $fields_values, $no_quote_fields = false)
212
+	{
213
+		$this->logDeprecation();
214
+		$res = $this->query($this->INSERTquery($table, $fields_values, $no_quote_fields));
215
+		if ($this->debugOutput) {
216
+			$this->debug('exec_INSERTquery');
217
+		}
218
+		foreach ($this->postProcessHookObjects as $hookObject) {
219
+			/** @var $hookObject PostProcessQueryHookInterface */
220
+			$hookObject->exec_INSERTquery_postProcessAction($table, $fields_values, $no_quote_fields, $this);
221
+		}
222
+		return $res;
223
+	}
224
+
225
+	/**
226
+	 * Creates and executes an INSERT SQL-statement for $table with multiple rows.
227
+	 *
228
+	 * @param string $table Table name
229
+	 * @param array $fields Field names
230
+	 * @param array $rows Table rows. Each row should be an array with field values mapping to $fields
231
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
232
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
233
+	 */
234
+	public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = false)
235
+	{
236
+		$this->logDeprecation();
237
+		$res = $this->query($this->INSERTmultipleRows($table, $fields, $rows, $no_quote_fields));
238
+		if ($this->debugOutput) {
239
+			$this->debug('exec_INSERTmultipleRows');
240
+		}
241
+		foreach ($this->postProcessHookObjects as $hookObject) {
242
+			/** @var $hookObject PostProcessQueryHookInterface */
243
+			$hookObject->exec_INSERTmultipleRows_postProcessAction($table, $fields, $rows, $no_quote_fields, $this);
244
+		}
245
+		return $res;
246
+	}
247
+
248
+	/**
249
+	 * Creates and executes an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
250
+	 * Using this function specifically allow us to handle BLOB and CLOB fields depending on DB
251
+	 *
252
+	 * @param string $table Database tablename
253
+	 * @param string $where WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
254
+	 * @param array $fields_values Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
255
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
256
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
257
+	 */
258
+	public function exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields = false)
259
+	{
260
+		$this->logDeprecation();
261
+		$res = $this->query($this->UPDATEquery($table, $where, $fields_values, $no_quote_fields));
262
+		if ($this->debugOutput) {
263
+			$this->debug('exec_UPDATEquery');
264
+		}
265
+		foreach ($this->postProcessHookObjects as $hookObject) {
266
+			/** @var $hookObject PostProcessQueryHookInterface */
267
+			$hookObject->exec_UPDATEquery_postProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
268
+		}
269
+		return $res;
270
+	}
271
+
272
+	/**
273
+	 * Creates and executes a DELETE SQL-statement for $table where $where-clause
274
+	 *
275
+	 * @param string $table Database tablename
276
+	 * @param string $where WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
277
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
278
+	 */
279
+	public function exec_DELETEquery($table, $where)
280
+	{
281
+		$this->logDeprecation();
282
+		$res = $this->query($this->DELETEquery($table, $where));
283
+		if ($this->debugOutput) {
284
+			$this->debug('exec_DELETEquery');
285
+		}
286
+		foreach ($this->postProcessHookObjects as $hookObject) {
287
+			/** @var $hookObject PostProcessQueryHookInterface */
288
+			$hookObject->exec_DELETEquery_postProcessAction($table, $where, $this);
289
+		}
290
+		return $res;
291
+	}
292
+
293
+	/**
294
+	 * Creates and executes a SELECT SQL-statement
295
+	 * Using this function specifically allow us to handle the LIMIT feature independently of DB.
296
+	 *
297
+	 * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
298
+	 * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
299
+	 * @param string $where_clause Additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
300
+	 * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
301
+	 * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
302
+	 * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
303
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
304
+	 */
305
+	public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
306
+	{
307
+		$this->logDeprecation();
308
+		$query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
309
+		$res = $this->query($query);
310
+		if ($this->debugOutput) {
311
+			$this->debug('exec_SELECTquery');
312
+		}
313
+		if ($this->explainOutput) {
314
+			$this->explain($query, $from_table, $res->num_rows);
315
+		}
316
+		foreach ($this->postProcessHookObjects as $hookObject) {
317
+			/** @var $hookObject PostProcessQueryHookInterface */
318
+			$hookObject->exec_SELECTquery_postProcessAction($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $this);
319
+		}
320
+		return $res;
321
+	}
322
+
323
+	/**
324
+	 * Creates and executes a SELECT query, selecting fields ($select) from two/three tables joined
325
+	 * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
326
+	 * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
327
+	 * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
328
+	 *
329
+	 * @param string $select Field list for SELECT
330
+	 * @param string $local_table Tablename, local table
331
+	 * @param string $mm_table Tablename, relation table
332
+	 * @param string $foreign_table Tablename, foreign table
333
+	 * @param string $whereClause Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT! You have to prepend 'AND ' to this parameter yourself!
334
+	 * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
335
+	 * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
336
+	 * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
337
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
338
+	 * @see exec_SELECTquery()
339
+	 */
340
+	public function exec_SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
341
+	{
342
+		$this->logDeprecation();
343
+		$queryParts = $this->getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause, $groupBy, $orderBy, $limit);
344
+		return $this->exec_SELECT_queryArray($queryParts);
345
+	}
346
+
347
+	/**
348
+	 * Executes a select based on input query parts array
349
+	 *
350
+	 * @param array $queryParts Query parts array
351
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
352
+	 * @see exec_SELECTquery()
353
+	 */
354
+	public function exec_SELECT_queryArray($queryParts)
355
+	{
356
+		$this->logDeprecation();
357
+		return $this->exec_SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT']);
358
+	}
359
+
360
+	/**
361
+	 * Creates and executes a SELECT SQL-statement AND traverse result set and returns array with records in.
362
+	 *
363
+	 * @param string $select_fields List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
364
+	 * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
365
+	 * @param string $where_clause Additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
366
+	 * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
367
+	 * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
368
+	 * @param string $limit Optional LIMIT value ([begin,]max), if none, supply blank string.
369
+	 * @param string $uidIndexField If set, the result array will carry this field names value as index. Requires that field to be selected of course!
370
+	 * @return array|NULL Array of rows, or NULL in case of SQL error
371
+	 * @see exec_SELECTquery()
372
+	 * @throws \InvalidArgumentException
373
+	 */
374
+	public function exec_SELECTgetRows($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $uidIndexField = '')
375
+	{
376
+		$this->logDeprecation();
377
+		$res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
378
+		if ($this->sql_error()) {
379
+			$this->sql_free_result($res);
380
+			return null;
381
+		}
382
+		$output = [];
383
+		$firstRecord = true;
384
+		while ($record = $this->sql_fetch_assoc($res)) {
385
+			if ($uidIndexField) {
386
+				if ($firstRecord) {
387
+					$firstRecord = false;
388
+					if (!array_key_exists($uidIndexField, $record)) {
389
+						$this->sql_free_result($res);
390
+						throw new \InvalidArgumentException('The given $uidIndexField "' . $uidIndexField . '" is not available in the result.', 1432933855);
391
+					}
392
+				}
393
+				$output[$record[$uidIndexField]] = $record;
394
+			} else {
395
+				$output[] = $record;
396
+			}
397
+		}
398
+		$this->sql_free_result($res);
399
+		return $output;
400
+	}
401
+
402
+	/**
403
+	 * Creates and executes a SELECT SQL-statement AND gets a result set and returns an array with a single record in.
404
+	 * LIMIT is automatically set to 1 and can not be overridden.
405
+	 *
406
+	 * @param string $select_fields List of fields to select from the table.
407
+	 * @param string $from_table Table(s) from which to select.
408
+	 * @param string $where_clause Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
409
+	 * @param string $groupBy Optional GROUP BY field(s), if none, supply blank string.
410
+	 * @param string $orderBy Optional ORDER BY field(s), if none, supply blank string.
411
+	 * @param bool $numIndex If set, the result will be fetched with sql_fetch_row, otherwise sql_fetch_assoc will be used.
412
+	 * @return array|FALSE|NULL Single row, FALSE on empty result, NULL on error
413
+	 */
414
+	public function exec_SELECTgetSingleRow($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $numIndex = false)
415
+	{
416
+		$this->logDeprecation();
417
+		$res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, '1');
418
+		$output = null;
419
+		if ($res !== false) {
420
+			if ($numIndex) {
421
+				$output = $this->sql_fetch_row($res);
422
+			} else {
423
+				$output = $this->sql_fetch_assoc($res);
424
+			}
425
+			$this->sql_free_result($res);
426
+		}
427
+		return $output;
428
+	}
429
+
430
+	/**
431
+	 * Counts the number of rows in a table.
432
+	 *
433
+	 * @param string $field Name of the field to use in the COUNT() expression (e.g. '*')
434
+	 * @param string $table Name of the table to count rows for
435
+	 * @param string $where (optional) WHERE statement of the query
436
+	 * @return mixed Number of rows counter (int) or FALSE if something went wrong (bool)
437
+	 */
438
+	public function exec_SELECTcountRows($field, $table, $where = '1=1')
439
+	{
440
+		$this->logDeprecation();
441
+		$count = false;
442
+		$resultSet = $this->exec_SELECTquery('COUNT(' . $field . ')', $table, $where);
443
+		if ($resultSet !== false) {
444
+			list($count) = $this->sql_fetch_row($resultSet);
445
+			$count = (int)$count;
446
+			$this->sql_free_result($resultSet);
447
+		}
448
+		return $count;
449
+	}
450
+
451
+	/**
452
+	 * Truncates a table.
453
+	 *
454
+	 * @param string $table Database tablename
455
+	 * @return mixed Result from handler
456
+	 */
457
+	public function exec_TRUNCATEquery($table)
458
+	{
459
+		$this->logDeprecation();
460
+		$res = $this->query($this->TRUNCATEquery($table));
461
+		if ($this->debugOutput) {
462
+			$this->debug('exec_TRUNCATEquery');
463
+		}
464
+		foreach ($this->postProcessHookObjects as $hookObject) {
465
+			/** @var $hookObject PostProcessQueryHookInterface */
466
+			$hookObject->exec_TRUNCATEquery_postProcessAction($table, $this);
467
+		}
468
+		return $res;
469
+	}
470
+
471
+	/**
472
+	 * Central query method. Also checks if there is a database connection.
473
+	 * Use this to execute database queries instead of directly calling $this->link->query()
474
+	 *
475
+	 * @param string $query The query to send to the database
476
+	 * @return bool|\mysqli_result
477
+	 */
478
+	protected function query($query)
479
+	{
480
+		$this->logDeprecation();
481
+		if (!$this->isConnected) {
482
+			$this->connectDB();
483
+		}
484
+		return $this->link->query($query);
485
+	}
486
+
487
+	/**************************************
488 488
      *
489 489
      * Query building
490 490
      *
491 491
      **************************************/
492
-    /**
493
-     * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
494
-     *
495
-     * @param string $table See exec_INSERTquery()
496
-     * @param array $fields_values See exec_INSERTquery()
497
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
498
-     * @return string|NULL Full SQL query for INSERT, NULL if $fields_values is empty
499
-     */
500
-    public function INSERTquery($table, $fields_values, $no_quote_fields = false)
501
-    {
502
-        $this->logDeprecation();
503
-        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
504
-        // function (contrary to values in the arrays which may be insecure).
505
-        if (!is_array($fields_values) || empty($fields_values)) {
506
-            return null;
507
-        }
508
-        foreach ($this->preProcessHookObjects as $hookObject) {
509
-            $hookObject->INSERTquery_preProcessAction($table, $fields_values, $no_quote_fields, $this);
510
-        }
511
-        // Quote and escape values
512
-        $fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
513
-        // Build query
514
-        $query = 'INSERT INTO ' . $table . ' (' . implode(',', array_keys($fields_values)) . ') VALUES ' . '(' . implode(',', $fields_values) . ')';
515
-        // Return query
516
-        if ($this->debugOutput || $this->store_lastBuiltQuery) {
517
-            $this->debug_lastBuiltQuery = $query;
518
-        }
519
-        return $query;
520
-    }
521
-
522
-    /**
523
-     * Creates an INSERT SQL-statement for $table with multiple rows.
524
-     *
525
-     * @param string $table Table name
526
-     * @param array $fields Field names
527
-     * @param array $rows Table rows. Each row should be an array with field values mapping to $fields
528
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
529
-     * @return string|NULL Full SQL query for INSERT, NULL if $rows is empty
530
-     */
531
-    public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = false)
532
-    {
533
-        $this->logDeprecation();
534
-        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
535
-        // function (contrary to values in the arrays which may be insecure).
536
-        if (empty($rows)) {
537
-            return null;
538
-        }
539
-        foreach ($this->preProcessHookObjects as $hookObject) {
540
-            /** @var $hookObject PreProcessQueryHookInterface */
541
-            $hookObject->INSERTmultipleRows_preProcessAction($table, $fields, $rows, $no_quote_fields, $this);
542
-        }
543
-        // Build query
544
-        $query = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES ';
545
-        $rowSQL = [];
546
-        foreach ($rows as $row) {
547
-            // Quote and escape values
548
-            $row = $this->fullQuoteArray($row, $table, $no_quote_fields);
549
-            $rowSQL[] = '(' . implode(', ', $row) . ')';
550
-        }
551
-        $query .= implode(', ', $rowSQL);
552
-        // Return query
553
-        if ($this->debugOutput || $this->store_lastBuiltQuery) {
554
-            $this->debug_lastBuiltQuery = $query;
555
-        }
556
-        return $query;
557
-    }
558
-
559
-    /**
560
-     * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
561
-     *
562
-     *
563
-     * @param string $table See exec_UPDATEquery()
564
-     * @param string $where See exec_UPDATEquery()
565
-     * @param array $fields_values See exec_UPDATEquery()
566
-     * @param bool|array|string $no_quote_fields See fullQuoteArray()
567
-     * @throws \InvalidArgumentException
568
-     * @return string Full SQL query for UPDATE
569
-     */
570
-    public function UPDATEquery($table, $where, $fields_values, $no_quote_fields = false)
571
-    {
572
-        $this->logDeprecation();
573
-        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
574
-        // function (contrary to values in the arrays which may be insecure).
575
-        if (is_string($where)) {
576
-            foreach ($this->preProcessHookObjects as $hookObject) {
577
-                /** @var $hookObject PreProcessQueryHookInterface */
578
-                $hookObject->UPDATEquery_preProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
579
-            }
580
-            $fields = [];
581
-            if (is_array($fields_values) && !empty($fields_values)) {
582
-                // Quote and escape values
583
-                $nArr = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
584
-                foreach ($nArr as $k => $v) {
585
-                    $fields[] = $k . '=' . $v;
586
-                }
587
-            }
588
-            // Build query
589
-            $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) . ((string)$where !== '' ? ' WHERE ' . $where : '');
590
-            if ($this->debugOutput || $this->store_lastBuiltQuery) {
591
-                $this->debug_lastBuiltQuery = $query;
592
-            }
593
-            return $query;
594
-        } else {
595
-            throw new \InvalidArgumentException('TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !', 1270853880);
596
-        }
597
-    }
598
-
599
-    /**
600
-     * Creates a DELETE SQL-statement for $table where $where-clause
601
-     *
602
-     * @param string $table See exec_DELETEquery()
603
-     * @param string $where See exec_DELETEquery()
604
-     * @return string Full SQL query for DELETE
605
-     * @throws \InvalidArgumentException
606
-     */
607
-    public function DELETEquery($table, $where)
608
-    {
609
-        $this->logDeprecation();
610
-        if (is_string($where)) {
611
-            foreach ($this->preProcessHookObjects as $hookObject) {
612
-                /** @var $hookObject PreProcessQueryHookInterface */
613
-                $hookObject->DELETEquery_preProcessAction($table, $where, $this);
614
-            }
615
-            // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
616
-            $query = 'DELETE FROM ' . $table . ((string)$where !== '' ? ' WHERE ' . $where : '');
617
-            if ($this->debugOutput || $this->store_lastBuiltQuery) {
618
-                $this->debug_lastBuiltQuery = $query;
619
-            }
620
-            return $query;
621
-        } else {
622
-            throw new \InvalidArgumentException('TYPO3 Fatal Error: "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !', 1270853881);
623
-        }
624
-    }
625
-
626
-    /**
627
-     * Creates a SELECT SQL-statement
628
-     *
629
-     * @param string $select_fields See exec_SELECTquery()
630
-     * @param string $from_table See exec_SELECTquery()
631
-     * @param string $where_clause See exec_SELECTquery()
632
-     * @param string $groupBy See exec_SELECTquery()
633
-     * @param string $orderBy See exec_SELECTquery()
634
-     * @param string $limit See exec_SELECTquery()
635
-     * @return string Full SQL query for SELECT
636
-     */
637
-    public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
638
-    {
639
-        $this->logDeprecation();
640
-        foreach ($this->preProcessHookObjects as $hookObject) {
641
-            /** @var $hookObject PreProcessQueryHookInterface */
642
-            $hookObject->SELECTquery_preProcessAction($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit, $this);
643
-        }
644
-        // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
645
-        // Build basic query
646
-        $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
647
-        // Group by
648
-        $query .= (string)$groupBy !== '' ? ' GROUP BY ' . $groupBy : '';
649
-        // Order by
650
-        $query .= (string)$orderBy !== '' ? ' ORDER BY ' . $orderBy : '';
651
-        // Group by
652
-        $query .= (string)$limit !== '' ? ' LIMIT ' . $limit : '';
653
-        // Return query
654
-        if ($this->debugOutput || $this->store_lastBuiltQuery) {
655
-            $this->debug_lastBuiltQuery = $query;
656
-        }
657
-        return $query;
658
-    }
659
-
660
-    /**
661
-     * Creates a SELECT SQL-statement to be used as subquery within another query.
662
-     * BEWARE: This method should not be overridden within DBAL to prevent quoting from happening.
663
-     *
664
-     * @param string $select_fields List of fields to select from the table.
665
-     * @param string $from_table Table from which to select.
666
-     * @param string $where_clause Conditional WHERE statement
667
-     * @return string Full SQL query for SELECT
668
-     */
669
-    public function SELECTsubquery($select_fields, $from_table, $where_clause)
670
-    {
671
-        $this->logDeprecation();
672
-        // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
673
-        // Build basic query:
674
-        $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
675
-        // Return query
676
-        if ($this->debugOutput || $this->store_lastBuiltQuery) {
677
-            $this->debug_lastBuiltQuery = $query;
678
-        }
679
-        return $query;
680
-    }
681
-
682
-    /**
683
-     * Creates a SELECT query, selecting fields ($select) from two/three tables joined
684
-     * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
685
-     * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
686
-     * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
687
-     *
688
-     * @param string $select See exec_SELECT_mm_query()
689
-     * @param string $local_table See exec_SELECT_mm_query()
690
-     * @param string $mm_table See exec_SELECT_mm_query()
691
-     * @param string $foreign_table See exec_SELECT_mm_query()
692
-     * @param string $whereClause See exec_SELECT_mm_query()
693
-     * @param string $groupBy See exec_SELECT_mm_query()
694
-     * @param string $orderBy See exec_SELECT_mm_query()
695
-     * @param string $limit See exec_SELECT_mm_query()
696
-     * @return string Full SQL query for SELECT
697
-     * @see SELECTquery()
698
-     */
699
-    public function SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
700
-    {
701
-        $this->logDeprecation();
702
-        $queryParts = $this->getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause, $groupBy, $orderBy, $limit);
703
-        return $this->SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT']);
704
-    }
705
-
706
-    /**
707
-     * Creates a TRUNCATE TABLE SQL-statement
708
-     *
709
-     * @param string $table See exec_TRUNCATEquery()
710
-     * @return string Full SQL query for TRUNCATE TABLE
711
-     */
712
-    public function TRUNCATEquery($table)
713
-    {
714
-        $this->logDeprecation();
715
-        foreach ($this->preProcessHookObjects as $hookObject) {
716
-            /** @var $hookObject PreProcessQueryHookInterface */
717
-            $hookObject->TRUNCATEquery_preProcessAction($table, $this);
718
-        }
719
-        // Table should be "SQL-injection-safe" when supplied to this function
720
-        // Build basic query:
721
-        $query = 'TRUNCATE TABLE ' . $table;
722
-        // Return query:
723
-        if ($this->debugOutput || $this->store_lastBuiltQuery) {
724
-            $this->debug_lastBuiltQuery = $query;
725
-        }
726
-        return $query;
727
-    }
728
-
729
-    /**
730
-     * Returns a WHERE clause that can find a value ($value) in a list field ($field)
731
-     * For instance a record in the database might contain a list of numbers,
732
-     * "34,234,5" (with no spaces between). This query would be able to select that
733
-     * record based on the value "34", "234" or "5" regardless of their position in
734
-     * the list (left, middle or right).
735
-     * The value must not contain a comma (,)
736
-     * Is nice to look up list-relations to records or files in TYPO3 database tables.
737
-     *
738
-     * @param string $field Field name
739
-     * @param string $value Value to find in list
740
-     * @param string $table Table in which we are searching (for DBAL detection of quoteStr() method)
741
-     * @return string WHERE clause for a query
742
-     * @throws \InvalidArgumentException
743
-     */
744
-    public function listQuery($field, $value, $table)
745
-    {
746
-        $this->logDeprecation();
747
-        $value = (string)$value;
748
-        if (strpos($value, ',') !== false) {
749
-            throw new \InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !', 1294585862);
750
-        }
751
-        $pattern = $this->quoteStr($value, $table);
752
-        $where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
753
-        return $where;
754
-    }
755
-
756
-    /**
757
-     * Returns a WHERE clause which will make an AND or OR search for the words in the $searchWords array in any of the fields in array $fields.
758
-     *
759
-     * @param array $searchWords Array of search words
760
-     * @param array $fields Array of fields
761
-     * @param string $table Table in which we are searching (for DBAL detection of quoteStr() method)
762
-     * @param string $constraint How multiple search words have to match ('AND' or 'OR')
763
-     * @return string WHERE clause for search
764
-     */
765
-    public function searchQuery($searchWords, $fields, $table, $constraint = self::AND_Constraint)
766
-    {
767
-        $this->logDeprecation();
768
-        switch ($constraint) {
769
-            case self::OR_Constraint:
770
-                $constraint = 'OR';
771
-                break;
772
-            default:
773
-                $constraint = 'AND';
774
-        }
775
-
776
-        $queryParts = [];
777
-        foreach ($searchWords as $sw) {
778
-            $like = ' LIKE \'%' . $this->quoteStr($this->escapeStrForLike($sw, $table), $table) . '%\'';
779
-            $queryParts[] = $table . '.' . implode(($like . ' OR ' . $table . '.'), $fields) . $like;
780
-        }
781
-        $query = '(' . implode(') ' . $constraint . ' (', $queryParts) . ')';
782
-
783
-        return $query;
784
-    }
785
-
786
-    /**************************************
492
+	/**
493
+	 * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
494
+	 *
495
+	 * @param string $table See exec_INSERTquery()
496
+	 * @param array $fields_values See exec_INSERTquery()
497
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
498
+	 * @return string|NULL Full SQL query for INSERT, NULL if $fields_values is empty
499
+	 */
500
+	public function INSERTquery($table, $fields_values, $no_quote_fields = false)
501
+	{
502
+		$this->logDeprecation();
503
+		// Table and fieldnames should be "SQL-injection-safe" when supplied to this
504
+		// function (contrary to values in the arrays which may be insecure).
505
+		if (!is_array($fields_values) || empty($fields_values)) {
506
+			return null;
507
+		}
508
+		foreach ($this->preProcessHookObjects as $hookObject) {
509
+			$hookObject->INSERTquery_preProcessAction($table, $fields_values, $no_quote_fields, $this);
510
+		}
511
+		// Quote and escape values
512
+		$fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
513
+		// Build query
514
+		$query = 'INSERT INTO ' . $table . ' (' . implode(',', array_keys($fields_values)) . ') VALUES ' . '(' . implode(',', $fields_values) . ')';
515
+		// Return query
516
+		if ($this->debugOutput || $this->store_lastBuiltQuery) {
517
+			$this->debug_lastBuiltQuery = $query;
518
+		}
519
+		return $query;
520
+	}
521
+
522
+	/**
523
+	 * Creates an INSERT SQL-statement for $table with multiple rows.
524
+	 *
525
+	 * @param string $table Table name
526
+	 * @param array $fields Field names
527
+	 * @param array $rows Table rows. Each row should be an array with field values mapping to $fields
528
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
529
+	 * @return string|NULL Full SQL query for INSERT, NULL if $rows is empty
530
+	 */
531
+	public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = false)
532
+	{
533
+		$this->logDeprecation();
534
+		// Table and fieldnames should be "SQL-injection-safe" when supplied to this
535
+		// function (contrary to values in the arrays which may be insecure).
536
+		if (empty($rows)) {
537
+			return null;
538
+		}
539
+		foreach ($this->preProcessHookObjects as $hookObject) {
540
+			/** @var $hookObject PreProcessQueryHookInterface */
541
+			$hookObject->INSERTmultipleRows_preProcessAction($table, $fields, $rows, $no_quote_fields, $this);
542
+		}
543
+		// Build query
544
+		$query = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES ';
545
+		$rowSQL = [];
546
+		foreach ($rows as $row) {
547
+			// Quote and escape values
548
+			$row = $this->fullQuoteArray($row, $table, $no_quote_fields);
549
+			$rowSQL[] = '(' . implode(', ', $row) . ')';
550
+		}
551
+		$query .= implode(', ', $rowSQL);
552
+		// Return query
553
+		if ($this->debugOutput || $this->store_lastBuiltQuery) {
554
+			$this->debug_lastBuiltQuery = $query;
555
+		}
556
+		return $query;
557
+	}
558
+
559
+	/**
560
+	 * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
561
+	 *
562
+	 *
563
+	 * @param string $table See exec_UPDATEquery()
564
+	 * @param string $where See exec_UPDATEquery()
565
+	 * @param array $fields_values See exec_UPDATEquery()
566
+	 * @param bool|array|string $no_quote_fields See fullQuoteArray()
567
+	 * @throws \InvalidArgumentException
568
+	 * @return string Full SQL query for UPDATE
569
+	 */
570
+	public function UPDATEquery($table, $where, $fields_values, $no_quote_fields = false)
571
+	{
572
+		$this->logDeprecation();
573
+		// Table and fieldnames should be "SQL-injection-safe" when supplied to this
574
+		// function (contrary to values in the arrays which may be insecure).
575
+		if (is_string($where)) {
576
+			foreach ($this->preProcessHookObjects as $hookObject) {
577
+				/** @var $hookObject PreProcessQueryHookInterface */
578
+				$hookObject->UPDATEquery_preProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
579
+			}
580
+			$fields = [];
581
+			if (is_array($fields_values) && !empty($fields_values)) {
582
+				// Quote and escape values
583
+				$nArr = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
584
+				foreach ($nArr as $k => $v) {
585
+					$fields[] = $k . '=' . $v;
586
+				}
587
+			}
588
+			// Build query
589
+			$query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) . ((string)$where !== '' ? ' WHERE ' . $where : '');
590
+			if ($this->debugOutput || $this->store_lastBuiltQuery) {
591
+				$this->debug_lastBuiltQuery = $query;
592
+			}
593
+			return $query;
594
+		} else {
595
+			throw new \InvalidArgumentException('TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !', 1270853880);
596
+		}
597
+	}
598
+
599
+	/**
600
+	 * Creates a DELETE SQL-statement for $table where $where-clause
601
+	 *
602
+	 * @param string $table See exec_DELETEquery()
603
+	 * @param string $where See exec_DELETEquery()
604
+	 * @return string Full SQL query for DELETE
605
+	 * @throws \InvalidArgumentException
606
+	 */
607
+	public function DELETEquery($table, $where)
608
+	{
609
+		$this->logDeprecation();
610
+		if (is_string($where)) {
611
+			foreach ($this->preProcessHookObjects as $hookObject) {
612
+				/** @var $hookObject PreProcessQueryHookInterface */
613
+				$hookObject->DELETEquery_preProcessAction($table, $where, $this);
614
+			}
615
+			// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
616
+			$query = 'DELETE FROM ' . $table . ((string)$where !== '' ? ' WHERE ' . $where : '');
617
+			if ($this->debugOutput || $this->store_lastBuiltQuery) {
618
+				$this->debug_lastBuiltQuery = $query;
619
+			}
620
+			return $query;
621
+		} else {
622
+			throw new \InvalidArgumentException('TYPO3 Fatal Error: "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !', 1270853881);
623
+		}
624
+	}
625
+
626
+	/**
627
+	 * Creates a SELECT SQL-statement
628
+	 *
629
+	 * @param string $select_fields See exec_SELECTquery()
630
+	 * @param string $from_table See exec_SELECTquery()
631
+	 * @param string $where_clause See exec_SELECTquery()
632
+	 * @param string $groupBy See exec_SELECTquery()
633
+	 * @param string $orderBy See exec_SELECTquery()
634
+	 * @param string $limit See exec_SELECTquery()
635
+	 * @return string Full SQL query for SELECT
636
+	 */
637
+	public function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '')
638
+	{
639
+		$this->logDeprecation();
640
+		foreach ($this->preProcessHookObjects as $hookObject) {
641
+			/** @var $hookObject PreProcessQueryHookInterface */
642
+			$hookObject->SELECTquery_preProcessAction($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit, $this);
643
+		}
644
+		// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
645
+		// Build basic query
646
+		$query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
647
+		// Group by
648
+		$query .= (string)$groupBy !== '' ? ' GROUP BY ' . $groupBy : '';
649
+		// Order by
650
+		$query .= (string)$orderBy !== '' ? ' ORDER BY ' . $orderBy : '';
651
+		// Group by
652
+		$query .= (string)$limit !== '' ? ' LIMIT ' . $limit : '';
653
+		// Return query
654
+		if ($this->debugOutput || $this->store_lastBuiltQuery) {
655
+			$this->debug_lastBuiltQuery = $query;
656
+		}
657
+		return $query;
658
+	}
659
+
660
+	/**
661
+	 * Creates a SELECT SQL-statement to be used as subquery within another query.
662
+	 * BEWARE: This method should not be overridden within DBAL to prevent quoting from happening.
663
+	 *
664
+	 * @param string $select_fields List of fields to select from the table.
665
+	 * @param string $from_table Table from which to select.
666
+	 * @param string $where_clause Conditional WHERE statement
667
+	 * @return string Full SQL query for SELECT
668
+	 */
669
+	public function SELECTsubquery($select_fields, $from_table, $where_clause)
670
+	{
671
+		$this->logDeprecation();
672
+		// Table and fieldnames should be "SQL-injection-safe" when supplied to this function
673
+		// Build basic query:
674
+		$query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
675
+		// Return query
676
+		if ($this->debugOutput || $this->store_lastBuiltQuery) {
677
+			$this->debug_lastBuiltQuery = $query;
678
+		}
679
+		return $query;
680
+	}
681
+
682
+	/**
683
+	 * Creates a SELECT query, selecting fields ($select) from two/three tables joined
684
+	 * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
685
+	 * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
686
+	 * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
687
+	 *
688
+	 * @param string $select See exec_SELECT_mm_query()
689
+	 * @param string $local_table See exec_SELECT_mm_query()
690
+	 * @param string $mm_table See exec_SELECT_mm_query()
691
+	 * @param string $foreign_table See exec_SELECT_mm_query()
692
+	 * @param string $whereClause See exec_SELECT_mm_query()
693
+	 * @param string $groupBy See exec_SELECT_mm_query()
694
+	 * @param string $orderBy See exec_SELECT_mm_query()
695
+	 * @param string $limit See exec_SELECT_mm_query()
696
+	 * @return string Full SQL query for SELECT
697
+	 * @see SELECTquery()
698
+	 */
699
+	public function SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
700
+	{
701
+		$this->logDeprecation();
702
+		$queryParts = $this->getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause, $groupBy, $orderBy, $limit);
703
+		return $this->SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT']);
704
+	}
705
+
706
+	/**
707
+	 * Creates a TRUNCATE TABLE SQL-statement
708
+	 *
709
+	 * @param string $table See exec_TRUNCATEquery()
710
+	 * @return string Full SQL query for TRUNCATE TABLE
711
+	 */
712
+	public function TRUNCATEquery($table)
713
+	{
714
+		$this->logDeprecation();
715
+		foreach ($this->preProcessHookObjects as $hookObject) {
716
+			/** @var $hookObject PreProcessQueryHookInterface */
717
+			$hookObject->TRUNCATEquery_preProcessAction($table, $this);
718
+		}
719
+		// Table should be "SQL-injection-safe" when supplied to this function
720
+		// Build basic query:
721
+		$query = 'TRUNCATE TABLE ' . $table;
722
+		// Return query:
723
+		if ($this->debugOutput || $this->store_lastBuiltQuery) {
724
+			$this->debug_lastBuiltQuery = $query;
725
+		}
726
+		return $query;
727
+	}
728
+
729
+	/**
730
+	 * Returns a WHERE clause that can find a value ($value) in a list field ($field)
731
+	 * For instance a record in the database might contain a list of numbers,
732
+	 * "34,234,5" (with no spaces between). This query would be able to select that
733
+	 * record based on the value "34", "234" or "5" regardless of their position in
734
+	 * the list (left, middle or right).
735
+	 * The value must not contain a comma (,)
736
+	 * Is nice to look up list-relations to records or files in TYPO3 database tables.
737
+	 *
738
+	 * @param string $field Field name
739
+	 * @param string $value Value to find in list
740
+	 * @param string $table Table in which we are searching (for DBAL detection of quoteStr() method)
741
+	 * @return string WHERE clause for a query
742
+	 * @throws \InvalidArgumentException
743
+	 */
744
+	public function listQuery($field, $value, $table)
745
+	{
746
+		$this->logDeprecation();
747
+		$value = (string)$value;
748
+		if (strpos($value, ',') !== false) {
749
+			throw new \InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !', 1294585862);
750
+		}
751
+		$pattern = $this->quoteStr($value, $table);
752
+		$where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
753
+		return $where;
754
+	}
755
+
756
+	/**
757
+	 * Returns a WHERE clause which will make an AND or OR search for the words in the $searchWords array in any of the fields in array $fields.
758
+	 *
759
+	 * @param array $searchWords Array of search words
760
+	 * @param array $fields Array of fields
761
+	 * @param string $table Table in which we are searching (for DBAL detection of quoteStr() method)
762
+	 * @param string $constraint How multiple search words have to match ('AND' or 'OR')
763
+	 * @return string WHERE clause for search
764
+	 */
765
+	public function searchQuery($searchWords, $fields, $table, $constraint = self::AND_Constraint)
766
+	{
767
+		$this->logDeprecation();
768
+		switch ($constraint) {
769
+			case self::OR_Constraint:
770
+				$constraint = 'OR';
771
+				break;
772
+			default:
773
+				$constraint = 'AND';
774
+		}
775
+
776
+		$queryParts = [];
777
+		foreach ($searchWords as $sw) {
778
+			$like = ' LIKE \'%' . $this->quoteStr($this->escapeStrForLike($sw, $table), $table) . '%\'';
779
+			$queryParts[] = $table . '.' . implode(($like . ' OR ' . $table . '.'), $fields) . $like;
780
+		}
781
+		$query = '(' . implode(') ' . $constraint . ' (', $queryParts) . ')';
782
+
783
+		return $query;
784
+	}
785
+
786
+	/**************************************
787 787
      *
788 788
      * Prepared Query Support
789 789
      *
790 790
      **************************************/
791
-    /**
792
-     * Creates a SELECT prepared SQL statement.
793
-     *
794
-     * @param string $select_fields See exec_SELECTquery()
795
-     * @param string $from_table See exec_SELECTquery()
796
-     * @param string $where_clause See exec_SELECTquery()
797
-     * @param string $groupBy See exec_SELECTquery()
798
-     * @param string $orderBy See exec_SELECTquery()
799
-     * @param string $limit See exec_SELECTquery()
800
-     * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as \Fab\Vidi\Database\PreparedStatement::PARAM_AUTOTYPE.
801
-     * @return \Fab\Vidi\Database\PreparedStatement Prepared statement
802
-     */
803
-    public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', array $input_parameters = [])
804
-    {
805
-        $this->logDeprecation();
806
-        $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
807
-        /** @var $preparedStatement \Fab\Vidi\Database\PreparedStatement */
808
-        $preparedStatement = GeneralUtility::makeInstance(\Fab\Vidi\Database\PreparedStatement::class, $query, $from_table, []);
809
-        // Bind values to parameters
810
-        foreach ($input_parameters as $key => $value) {
811
-            $preparedStatement->bindValue($key, $value, PreparedStatement::PARAM_AUTOTYPE);
812
-        }
813
-        // Return prepared statement
814
-        return $preparedStatement;
815
-    }
816
-
817
-    /**
818
-     * Creates a SELECT prepared SQL statement based on input query parts array
819
-     *
820
-     * @param array $queryParts Query parts array
821
-     * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as \Fab\Vidi\Database\PreparedStatement::PARAM_AUTOTYPE.
822
-     * @return \Fab\Vidi\Database\PreparedStatement Prepared statement
823
-     */
824
-    public function prepare_SELECTqueryArray(array $queryParts, array $input_parameters = [])
825
-    {
826
-        $this->logDeprecation();
827
-        return $this->prepare_SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT'], $input_parameters);
828
-    }
829
-
830
-    /**
831
-     * Prepares a prepared query.
832
-     *
833
-     * @param string $query The query to execute
834
-     * @param array $queryComponents The components of the query to execute
835
-     * @return \mysqli_stmt|object MySQLi statement / DBAL object
836
-     * @internal This method may only be called by \Fab\Vidi\Database\PreparedStatement
837
-     */
838
-    public function prepare_PREPAREDquery($query, array $queryComponents)
839
-    {
840
-        $this->logDeprecation();
841
-        if (!$this->isConnected) {
842
-            $this->connectDB();
843
-        }
844
-        $stmt = $this->link->stmt_init();
845
-        $success = $stmt->prepare($query);
846
-        if ($this->debugOutput) {
847
-            $this->debug('stmt_execute', $query);
848
-        }
849
-        return $success ? $stmt : null;
850
-    }
851
-
852
-    /**************************************
791
+	/**
792
+	 * Creates a SELECT prepared SQL statement.
793
+	 *
794
+	 * @param string $select_fields See exec_SELECTquery()
795
+	 * @param string $from_table See exec_SELECTquery()
796
+	 * @param string $where_clause See exec_SELECTquery()
797
+	 * @param string $groupBy See exec_SELECTquery()
798
+	 * @param string $orderBy See exec_SELECTquery()
799
+	 * @param string $limit See exec_SELECTquery()
800
+	 * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as \Fab\Vidi\Database\PreparedStatement::PARAM_AUTOTYPE.
801
+	 * @return \Fab\Vidi\Database\PreparedStatement Prepared statement
802
+	 */
803
+	public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', array $input_parameters = [])
804
+	{
805
+		$this->logDeprecation();
806
+		$query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
807
+		/** @var $preparedStatement \Fab\Vidi\Database\PreparedStatement */
808
+		$preparedStatement = GeneralUtility::makeInstance(\Fab\Vidi\Database\PreparedStatement::class, $query, $from_table, []);
809
+		// Bind values to parameters
810
+		foreach ($input_parameters as $key => $value) {
811
+			$preparedStatement->bindValue($key, $value, PreparedStatement::PARAM_AUTOTYPE);
812
+		}
813
+		// Return prepared statement
814
+		return $preparedStatement;
815
+	}
816
+
817
+	/**
818
+	 * Creates a SELECT prepared SQL statement based on input query parts array
819
+	 *
820
+	 * @param array $queryParts Query parts array
821
+	 * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as \Fab\Vidi\Database\PreparedStatement::PARAM_AUTOTYPE.
822
+	 * @return \Fab\Vidi\Database\PreparedStatement Prepared statement
823
+	 */
824
+	public function prepare_SELECTqueryArray(array $queryParts, array $input_parameters = [])
825
+	{
826
+		$this->logDeprecation();
827
+		return $this->prepare_SELECTquery($queryParts['SELECT'], $queryParts['FROM'], $queryParts['WHERE'], $queryParts['GROUPBY'], $queryParts['ORDERBY'], $queryParts['LIMIT'], $input_parameters);
828
+	}
829
+
830
+	/**
831
+	 * Prepares a prepared query.
832
+	 *
833
+	 * @param string $query The query to execute
834
+	 * @param array $queryComponents The components of the query to execute
835
+	 * @return \mysqli_stmt|object MySQLi statement / DBAL object
836
+	 * @internal This method may only be called by \Fab\Vidi\Database\PreparedStatement
837
+	 */
838
+	public function prepare_PREPAREDquery($query, array $queryComponents)
839
+	{
840
+		$this->logDeprecation();
841
+		if (!$this->isConnected) {
842
+			$this->connectDB();
843
+		}
844
+		$stmt = $this->link->stmt_init();
845
+		$success = $stmt->prepare($query);
846
+		if ($this->debugOutput) {
847
+			$this->debug('stmt_execute', $query);
848
+		}
849
+		return $success ? $stmt : null;
850
+	}
851
+
852
+	/**************************************
853 853
      *
854 854
      * Various helper functions
855 855
      *
@@ -859,1161 +859,1161 @@  discard block
 block discarded – undo
859 859
      * - stripping of excess ORDER BY/GROUP BY keywords
860 860
      *
861 861
      **************************************/
862
-    /**
863
-     * Escaping and quoting values for SQL statements.
864
-     *
865
-     * @param string $str Input string
866
-     * @param string $table Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
867
-     * @param bool $allowNull Whether to allow NULL values
868
-     * @return string Output string; Wrapped in single quotes and quotes in the string (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
869
-     * @see quoteStr()
870
-     */
871
-    public function fullQuoteStr($str, $table, $allowNull = false)
872
-    {
873
-        $this->logDeprecation();
874
-        if (!$this->isConnected) {
875
-            $this->connectDB();
876
-        }
877
-        if ($allowNull && $str === null) {
878
-            return 'NULL';
879
-        }
880
-        if (is_bool($str)) {
881
-            $str = (int)$str;
882
-        }
883
-
884
-        return '\'' . $this->link->real_escape_string($str) . '\'';
885
-    }
886
-
887
-    /**
888
-     * Will fullquote all values in the one-dimensional array so they are ready to "implode" for an sql query.
889
-     *
890
-     * @param array $arr Array with values (either associative or non-associative array)
891
-     * @param string $table Table name for which to quote
892
-     * @param bool|array|string $noQuote List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
893
-     * @param bool $allowNull Whether to allow NULL values
894
-     * @return array The input array with the values quoted
895
-     * @see cleanIntArray()
896
-     */
897
-    public function fullQuoteArray($arr, $table, $noQuote = false, $allowNull = false)
898
-    {
899
-        $this->logDeprecation();
900
-        if (is_string($noQuote)) {
901
-            $noQuote = explode(',', $noQuote);
902
-        } elseif (!is_array($noQuote)) {
903
-            $noQuote = (bool)$noQuote;
904
-        }
905
-        if ($noQuote === true) {
906
-            return $arr;
907
-        }
908
-        foreach ($arr as $k => $v) {
909
-            if ($noQuote === false || !in_array($k, $noQuote)) {
910
-                $arr[$k] = $this->fullQuoteStr($v, $table, $allowNull);
911
-            }
912
-        }
913
-        return $arr;
914
-    }
915
-
916
-    /**
917
-     * Substitution for PHP function "addslashes()"
918
-     * Use this function instead of the PHP addslashes() function when you build queries - this will prepare your code for DBAL.
919
-     * NOTICE: You must wrap the output of this function in SINGLE QUOTES to be DBAL compatible. Unless you have to apply the single quotes yourself you should rather use ->fullQuoteStr()!
920
-     *
921
-     * @param string $str Input string
922
-     * @param string $table Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
923
-     * @return string Output string; Quotes (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
924
-     * @see quoteStr()
925
-     */
926
-    public function quoteStr($str, $table)
927
-    {
928
-        $this->logDeprecation();
929
-        if (!$this->isConnected) {
930
-            $this->connectDB();
931
-        }
932
-        return $this->link->real_escape_string($str);
933
-    }
934
-
935
-    /**
936
-     * Escaping values for SQL LIKE statements.
937
-     *
938
-     * @param string $str Input string
939
-     * @param string $table Table name for which to escape string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
940
-     * @return string Output string; % and _ will be escaped with \ (or otherwise based on DBAL handler)
941
-     * @see quoteStr()
942
-     */
943
-    public function escapeStrForLike($str, $table)
944
-    {
945
-        $this->logDeprecation();
946
-        return addcslashes($str, '_%');
947
-    }
948
-
949
-    /**
950
-     * Will convert all values in the one-dimensional array to integers.
951
-     * Useful when you want to make sure an array contains only integers before imploding them in a select-list.
952
-     *
953
-     * @param array $arr Array with values
954
-     * @return array The input array with all values cast to (int)
955
-     * @see cleanIntList()
956
-     */
957
-    public function cleanIntArray($arr)
958
-    {
959
-        $this->logDeprecation();
960
-        return array_map('intval', $arr);
961
-    }
962
-
963
-    /**
964
-     * Will force all entries in the input comma list to integers
965
-     * Useful when you want to make sure a commalist of supposed integers really contain only integers; You want to know that when you don't trust content that could go into an SQL statement.
966
-     *
967
-     * @param string $list List of comma-separated values which should be integers
968
-     * @return string The input list but with every value cast to (int)
969
-     * @see cleanIntArray()
970
-     */
971
-    public function cleanIntList($list)
972
-    {
973
-        $this->logDeprecation();
974
-        return implode(',', GeneralUtility::intExplode(',', $list));
975
-    }
976
-
977
-    /**
978
-     * Removes the prefix "ORDER BY" from the input string.
979
-     * This function is used when you call the exec_SELECTquery() function and want to pass the ORDER BY parameter by can't guarantee that "ORDER BY" is not prefixed.
980
-     * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
981
-     *
982
-     * @param string $str eg. "ORDER BY title, uid
983
-     * @return string eg. "title, uid
984
-     * @see exec_SELECTquery(), stripGroupBy()
985
-     */
986
-    public function stripOrderBy($str)
987
-    {
988
-        $this->logDeprecation();
989
-        return preg_replace('/^(?:ORDER[[:space:]]*BY[[:space:]]*)+/i', '', trim($str));
990
-    }
991
-
992
-    /**
993
-     * Removes the prefix "GROUP BY" from the input string.
994
-     * This function is used when you call the SELECTquery() function and want to pass the GROUP BY parameter by can't guarantee that "GROUP BY" is not prefixed.
995
-     * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
996
-     *
997
-     * @param string $str eg. "GROUP BY title, uid
998
-     * @return string eg. "title, uid
999
-     * @see exec_SELECTquery(), stripOrderBy()
1000
-     */
1001
-    public function stripGroupBy($str)
1002
-    {
1003
-        $this->logDeprecation();
1004
-        return preg_replace('/^(?:GROUP[[:space:]]*BY[[:space:]]*)+/i', '', trim($str));
1005
-    }
1006
-
1007
-    /**
1008
-     * Returns the date and time formats compatible with the given database table.
1009
-     *
1010
-     * @param string $table Table name for which to return an empty date. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how date and time should be formatted).
1011
-     * @return array
1012
-     */
1013
-    public function getDateTimeFormats($table)
1014
-    {
1015
-        $this->logDeprecation();
1016
-        return QueryHelper::getDateTimeFormats();
1017
-    }
1018
-
1019
-    /**
1020
-     * Creates SELECT query components for selecting fields ($select) from two/three tables joined
1021
-     * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
1022
-     * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
1023
-     * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
1024
-     *
1025
-     * @param string $select See exec_SELECT_mm_query()
1026
-     * @param string $local_table See exec_SELECT_mm_query()
1027
-     * @param string $mm_table See exec_SELECT_mm_query()
1028
-     * @param string $foreign_table See exec_SELECT_mm_query()
1029
-     * @param string $whereClause See exec_SELECT_mm_query()
1030
-     * @param string $groupBy See exec_SELECT_mm_query()
1031
-     * @param string $orderBy See exec_SELECT_mm_query()
1032
-     * @param string $limit See exec_SELECT_mm_query()
1033
-     * @return array SQL query components
1034
-     */
1035
-    protected function getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
1036
-    {
1037
-        $foreign_table_as = $foreign_table == $local_table ? $foreign_table . StringUtility::getUniqueId('_join') : '';
1038
-        $mmWhere = $local_table ? $local_table . '.uid=' . $mm_table . '.uid_local' : '';
1039
-        $mmWhere .= ($local_table and $foreign_table) ? ' AND ' : '';
1040
-        $tables = ($local_table ? $local_table . ',' : '') . $mm_table;
1041
-        if ($foreign_table) {
1042
-            $mmWhere .= ($foreign_table_as ?: $foreign_table) . '.uid=' . $mm_table . '.uid_foreign';
1043
-            $tables .= ',' . $foreign_table . ($foreign_table_as ? ' AS ' . $foreign_table_as : '');
1044
-        }
1045
-        return [
1046
-            'SELECT' => $select,
1047
-            'FROM' => $tables,
1048
-            'WHERE' => $mmWhere . ' ' . $whereClause,
1049
-            'GROUPBY' => $groupBy,
1050
-            'ORDERBY' => $orderBy,
1051
-            'LIMIT' => $limit
1052
-        ];
1053
-    }
1054
-
1055
-    /**************************************
862
+	/**
863
+	 * Escaping and quoting values for SQL statements.
864
+	 *
865
+	 * @param string $str Input string
866
+	 * @param string $table Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
867
+	 * @param bool $allowNull Whether to allow NULL values
868
+	 * @return string Output string; Wrapped in single quotes and quotes in the string (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
869
+	 * @see quoteStr()
870
+	 */
871
+	public function fullQuoteStr($str, $table, $allowNull = false)
872
+	{
873
+		$this->logDeprecation();
874
+		if (!$this->isConnected) {
875
+			$this->connectDB();
876
+		}
877
+		if ($allowNull && $str === null) {
878
+			return 'NULL';
879
+		}
880
+		if (is_bool($str)) {
881
+			$str = (int)$str;
882
+		}
883
+
884
+		return '\'' . $this->link->real_escape_string($str) . '\'';
885
+	}
886
+
887
+	/**
888
+	 * Will fullquote all values in the one-dimensional array so they are ready to "implode" for an sql query.
889
+	 *
890
+	 * @param array $arr Array with values (either associative or non-associative array)
891
+	 * @param string $table Table name for which to quote
892
+	 * @param bool|array|string $noQuote List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
893
+	 * @param bool $allowNull Whether to allow NULL values
894
+	 * @return array The input array with the values quoted
895
+	 * @see cleanIntArray()
896
+	 */
897
+	public function fullQuoteArray($arr, $table, $noQuote = false, $allowNull = false)
898
+	{
899
+		$this->logDeprecation();
900
+		if (is_string($noQuote)) {
901
+			$noQuote = explode(',', $noQuote);
902
+		} elseif (!is_array($noQuote)) {
903
+			$noQuote = (bool)$noQuote;
904
+		}
905
+		if ($noQuote === true) {
906
+			return $arr;
907
+		}
908
+		foreach ($arr as $k => $v) {
909
+			if ($noQuote === false || !in_array($k, $noQuote)) {
910
+				$arr[$k] = $this->fullQuoteStr($v, $table, $allowNull);
911
+			}
912
+		}
913
+		return $arr;
914
+	}
915
+
916
+	/**
917
+	 * Substitution for PHP function "addslashes()"
918
+	 * Use this function instead of the PHP addslashes() function when you build queries - this will prepare your code for DBAL.
919
+	 * NOTICE: You must wrap the output of this function in SINGLE QUOTES to be DBAL compatible. Unless you have to apply the single quotes yourself you should rather use ->fullQuoteStr()!
920
+	 *
921
+	 * @param string $str Input string
922
+	 * @param string $table Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
923
+	 * @return string Output string; Quotes (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
924
+	 * @see quoteStr()
925
+	 */
926
+	public function quoteStr($str, $table)
927
+	{
928
+		$this->logDeprecation();
929
+		if (!$this->isConnected) {
930
+			$this->connectDB();
931
+		}
932
+		return $this->link->real_escape_string($str);
933
+	}
934
+
935
+	/**
936
+	 * Escaping values for SQL LIKE statements.
937
+	 *
938
+	 * @param string $str Input string
939
+	 * @param string $table Table name for which to escape string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
940
+	 * @return string Output string; % and _ will be escaped with \ (or otherwise based on DBAL handler)
941
+	 * @see quoteStr()
942
+	 */
943
+	public function escapeStrForLike($str, $table)
944
+	{
945
+		$this->logDeprecation();
946
+		return addcslashes($str, '_%');
947
+	}
948
+
949
+	/**
950
+	 * Will convert all values in the one-dimensional array to integers.
951
+	 * Useful when you want to make sure an array contains only integers before imploding them in a select-list.
952
+	 *
953
+	 * @param array $arr Array with values
954
+	 * @return array The input array with all values cast to (int)
955
+	 * @see cleanIntList()
956
+	 */
957
+	public function cleanIntArray($arr)
958
+	{
959
+		$this->logDeprecation();
960
+		return array_map('intval', $arr);
961
+	}
962
+
963
+	/**
964
+	 * Will force all entries in the input comma list to integers
965
+	 * Useful when you want to make sure a commalist of supposed integers really contain only integers; You want to know that when you don't trust content that could go into an SQL statement.
966
+	 *
967
+	 * @param string $list List of comma-separated values which should be integers
968
+	 * @return string The input list but with every value cast to (int)
969
+	 * @see cleanIntArray()
970
+	 */
971
+	public function cleanIntList($list)
972
+	{
973
+		$this->logDeprecation();
974
+		return implode(',', GeneralUtility::intExplode(',', $list));
975
+	}
976
+
977
+	/**
978
+	 * Removes the prefix "ORDER BY" from the input string.
979
+	 * This function is used when you call the exec_SELECTquery() function and want to pass the ORDER BY parameter by can't guarantee that "ORDER BY" is not prefixed.
980
+	 * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
981
+	 *
982
+	 * @param string $str eg. "ORDER BY title, uid
983
+	 * @return string eg. "title, uid
984
+	 * @see exec_SELECTquery(), stripGroupBy()
985
+	 */
986
+	public function stripOrderBy($str)
987
+	{
988
+		$this->logDeprecation();
989
+		return preg_replace('/^(?:ORDER[[:space:]]*BY[[:space:]]*)+/i', '', trim($str));
990
+	}
991
+
992
+	/**
993
+	 * Removes the prefix "GROUP BY" from the input string.
994
+	 * This function is used when you call the SELECTquery() function and want to pass the GROUP BY parameter by can't guarantee that "GROUP BY" is not prefixed.
995
+	 * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
996
+	 *
997
+	 * @param string $str eg. "GROUP BY title, uid
998
+	 * @return string eg. "title, uid
999
+	 * @see exec_SELECTquery(), stripOrderBy()
1000
+	 */
1001
+	public function stripGroupBy($str)
1002
+	{
1003
+		$this->logDeprecation();
1004
+		return preg_replace('/^(?:GROUP[[:space:]]*BY[[:space:]]*)+/i', '', trim($str));
1005
+	}
1006
+
1007
+	/**
1008
+	 * Returns the date and time formats compatible with the given database table.
1009
+	 *
1010
+	 * @param string $table Table name for which to return an empty date. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how date and time should be formatted).
1011
+	 * @return array
1012
+	 */
1013
+	public function getDateTimeFormats($table)
1014
+	{
1015
+		$this->logDeprecation();
1016
+		return QueryHelper::getDateTimeFormats();
1017
+	}
1018
+
1019
+	/**
1020
+	 * Creates SELECT query components for selecting fields ($select) from two/three tables joined
1021
+	 * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
1022
+	 * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
1023
+	 * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
1024
+	 *
1025
+	 * @param string $select See exec_SELECT_mm_query()
1026
+	 * @param string $local_table See exec_SELECT_mm_query()
1027
+	 * @param string $mm_table See exec_SELECT_mm_query()
1028
+	 * @param string $foreign_table See exec_SELECT_mm_query()
1029
+	 * @param string $whereClause See exec_SELECT_mm_query()
1030
+	 * @param string $groupBy See exec_SELECT_mm_query()
1031
+	 * @param string $orderBy See exec_SELECT_mm_query()
1032
+	 * @param string $limit See exec_SELECT_mm_query()
1033
+	 * @return array SQL query components
1034
+	 */
1035
+	protected function getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
1036
+	{
1037
+		$foreign_table_as = $foreign_table == $local_table ? $foreign_table . StringUtility::getUniqueId('_join') : '';
1038
+		$mmWhere = $local_table ? $local_table . '.uid=' . $mm_table . '.uid_local' : '';
1039
+		$mmWhere .= ($local_table and $foreign_table) ? ' AND ' : '';
1040
+		$tables = ($local_table ? $local_table . ',' : '') . $mm_table;
1041
+		if ($foreign_table) {
1042
+			$mmWhere .= ($foreign_table_as ?: $foreign_table) . '.uid=' . $mm_table . '.uid_foreign';
1043
+			$tables .= ',' . $foreign_table . ($foreign_table_as ? ' AS ' . $foreign_table_as : '');
1044
+		}
1045
+		return [
1046
+			'SELECT' => $select,
1047
+			'FROM' => $tables,
1048
+			'WHERE' => $mmWhere . ' ' . $whereClause,
1049
+			'GROUPBY' => $groupBy,
1050
+			'ORDERBY' => $orderBy,
1051
+			'LIMIT' => $limit
1052
+		];
1053
+	}
1054
+
1055
+	/**************************************
1056 1056
      *
1057 1057
      * MySQL(i) wrapper functions
1058 1058
      * (For use in your applications)
1059 1059
      *
1060 1060
      **************************************/
1061
-    /**
1062
-     * Executes query
1063
-     * MySQLi query() wrapper function
1064
-     * Beware: Use of this method should be avoided as it is experimentally supported by DBAL. You should consider
1065
-     * using exec_SELECTquery() and similar methods instead.
1066
-     *
1067
-     * @param string $query Query to execute
1068
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
1069
-     */
1070
-    public function sql_query($query)
1071
-    {
1072
-        $this->logDeprecation();
1073
-        $res = $this->query($query);
1074
-        if ($this->debugOutput) {
1075
-            $this->debug('sql_query', $query);
1076
-        }
1077
-        return $res;
1078
-    }
1079
-
1080
-    /**
1081
-     * Returns the error status on the last query() execution
1082
-     *
1083
-     * @return string MySQLi error string.
1084
-     */
1085
-    public function sql_error()
1086
-    {
1087
-        $this->logDeprecation();
1088
-        return $this->link->error;
1089
-    }
1090
-
1091
-    /**
1092
-     * Returns the error number on the last query() execution
1093
-     *
1094
-     * @return int MySQLi error number
1095
-     */
1096
-    public function sql_errno()
1097
-    {
1098
-        $this->logDeprecation();
1099
-        return $this->link->errno;
1100
-    }
1101
-
1102
-    /**
1103
-     * Returns the number of selected rows.
1104
-     *
1105
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1106
-     * @return int Number of resulting rows
1107
-     */
1108
-    public function sql_num_rows($res)
1109
-    {
1110
-        $this->logDeprecation();
1111
-        if ($this->debug_check_recordset($res)) {
1112
-            return $res->num_rows;
1113
-        } else {
1114
-            return false;
1115
-        }
1116
-    }
1117
-
1118
-    /**
1119
-     * Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.
1120
-     * MySQLi fetch_assoc() wrapper function
1121
-     *
1122
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1123
-     * @return array|bool Associative array of result row.
1124
-     */
1125
-    public function sql_fetch_assoc($res)
1126
-    {
1127
-        $this->logDeprecation();
1128
-        if ($this->debug_check_recordset($res)) {
1129
-            $result = $res->fetch_assoc();
1130
-            if ($result === null) {
1131
-                // Needed for compatibility
1132
-                $result = false;
1133
-            }
1134
-            return $result;
1135
-        } else {
1136
-            return false;
1137
-        }
1138
-    }
1139
-
1140
-    /**
1141
-     * Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.
1142
-     * The array contains the values in numerical indices.
1143
-     * MySQLi fetch_row() wrapper function
1144
-     *
1145
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1146
-     * @return array|bool Array with result rows.
1147
-     */
1148
-    public function sql_fetch_row($res)
1149
-    {
1150
-        $this->logDeprecation();
1151
-        if ($this->debug_check_recordset($res)) {
1152
-            $result = $res->fetch_row();
1153
-            if ($result === null) {
1154
-                // Needed for compatibility
1155
-                $result = false;
1156
-            }
1157
-            return $result;
1158
-        } else {
1159
-            return false;
1160
-        }
1161
-    }
1162
-
1163
-    /**
1164
-     * Free result memory
1165
-     * free_result() wrapper function
1166
-     *
1167
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1168
-     * @return bool Returns TRUE on success or FALSE on failure.
1169
-     */
1170
-    public function sql_free_result($res)
1171
-    {
1172
-        $this->logDeprecation();
1173
-        if ($this->debug_check_recordset($res) && is_object($res)) {
1174
-            $res->free();
1175
-            return true;
1176
-        } else {
1177
-            return false;
1178
-        }
1179
-    }
1180
-
1181
-    /**
1182
-     * Get the ID generated from the previous INSERT operation
1183
-     *
1184
-     * @return int The uid of the last inserted record.
1185
-     */
1186
-    public function sql_insert_id()
1187
-    {
1188
-        $this->logDeprecation();
1189
-        return $this->link->insert_id;
1190
-    }
1191
-
1192
-    /**
1193
-     * Returns the number of rows affected by the last INSERT, UPDATE or DELETE query
1194
-     *
1195
-     * @return int Number of rows affected by last query
1196
-     */
1197
-    public function sql_affected_rows()
1198
-    {
1199
-        return $this->link->affected_rows;
1200
-    }
1201
-
1202
-    /**
1203
-     * Move internal result pointer
1204
-     *
1205
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1206
-     * @param int $seek Seek result number.
1207
-     * @return bool Returns TRUE on success or FALSE on failure.
1208
-     */
1209
-    public function sql_data_seek($res, $seek)
1210
-    {
1211
-        $this->logDeprecation();
1212
-        if ($this->debug_check_recordset($res)) {
1213
-            return $res->data_seek($seek);
1214
-        } else {
1215
-            return false;
1216
-        }
1217
-    }
1218
-
1219
-    /**
1220
-     * Get the type of the specified field in a result
1221
-     * mysql_field_type() wrapper function
1222
-     *
1223
-     * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1224
-     * @param int $pointer Field index.
1225
-     * @return string Returns the name of the specified field index, or FALSE on error
1226
-     */
1227
-    public function sql_field_type($res, $pointer)
1228
-    {
1229
-        // mysql_field_type compatibility map
1230
-        // taken from: http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php#89117
1231
-        // Constant numbers see http://php.net/manual/en/mysqli.constants.php
1232
-        $mysql_data_type_hash = [
1233
-            1=>'tinyint',
1234
-            2=>'smallint',
1235
-            3=>'int',
1236
-            4=>'float',
1237
-            5=>'double',
1238
-            7=>'timestamp',
1239
-            8=>'bigint',
1240
-            9=>'mediumint',
1241
-            10=>'date',
1242
-            11=>'time',
1243
-            12=>'datetime',
1244
-            13=>'year',
1245
-            16=>'bit',
1246
-            //252 is currently mapped to all text and blob types (MySQL 5.0.51a)
1247
-            253=>'varchar',
1248
-            254=>'char',
1249
-            246=>'decimal'
1250
-        ];
1251
-        if ($this->debug_check_recordset($res)) {
1252
-            $metaInfo = $res->fetch_field_direct($pointer);
1253
-            if ($metaInfo === false) {
1254
-                return false;
1255
-            }
1256
-            return $mysql_data_type_hash[$metaInfo->type];
1257
-        } else {
1258
-            return false;
1259
-        }
1260
-    }
1261
-
1262
-    /**
1263
-     * Open a (persistent) connection to a MySQL server
1264
-     *
1265
-     * @return bool|void
1266
-     * @throws \RuntimeException
1267
-     */
1268
-    public function sql_pconnect()
1269
-    {
1270
-        if ($this->isConnected) {
1271
-            return $this->link;
1272
-        }
1273
-
1274
-        if (!extension_loaded('mysqli')) {
1275
-            throw new \RuntimeException(
1276
-                'Database Error: PHP mysqli extension not loaded. This is a must have for TYPO3 CMS!',
1277
-                1271492607
1278
-            );
1279
-        }
1280
-
1281
-        $host = $this->persistentDatabaseConnection
1282
-            ? 'p:' . $this->databaseHost
1283
-            : $this->databaseHost;
1284
-
1285
-        // We are not using the TYPO3 CMS shim here as the database parameters in this class
1286
-        // are settable externally. This requires building the connection parameter array
1287
-        // just in time when establishing the connection.
1288
-        $connection = \Doctrine\DBAL\DriverManager::getConnection([
1289
-            'driver' => 'mysqli',
1290
-            'wrapperClass' => Connection::class,
1291
-            'host' => $host,
1292
-            'port' => (int)$this->databasePort,
1293
-            'unix_socket' => $this->databaseSocket,
1294
-            'user' => $this->databaseUsername,
1295
-            'password' => $this->databaseUserPassword,
1296
-            'charset' => $this->connectionCharset,
1297
-        ]);
1298
-
1299
-        // Mimic the previous behavior of returning false on connection errors
1300
-        try {
1301
-            /** @var \Doctrine\DBAL\Driver\Mysqli\MysqliConnection $mysqliConnection */
1302
-            $mysqliConnection = $connection->getWrappedConnection();
1303
-            $this->link = $mysqliConnection->getWrappedResourceHandle();
1304
-        } catch (\Doctrine\DBAL\Exception\ConnectionException $exception) {
1305
-            return false;
1306
-        }
1307
-
1308
-        if ($connection->isConnected()) {
1309
-            $this->isConnected = true;
1310
-
1311
-            foreach ($this->initializeCommandsAfterConnect as $command) {
1312
-                if ($this->query($command) === false) {
1313
-                    GeneralUtility::sysLog(
1314
-                        'Could not initialize DB connection with query "' . $command . '": ' . $this->sql_error(),
1315
-                        'core',
1316
-                        GeneralUtility::SYSLOG_SEVERITY_ERROR
1317
-                    );
1318
-                }
1319
-            }
1320
-            $this->checkConnectionCharset();
1321
-        } else {
1322
-            // @todo This should raise an exception. Would be useful especially to work during installation.
1323
-            $error_msg = $this->link->connect_error;
1324
-            $this->link = null;
1325
-            GeneralUtility::sysLog(
1326
-                'Could not connect to MySQL server ' . $host . ' with user ' . $this->databaseUsername . ': '
1327
-                . $error_msg,
1328
-                'core',
1329
-                GeneralUtility::SYSLOG_SEVERITY_FATAL
1330
-            );
1331
-        }
1332
-
1333
-        return $this->link;
1334
-    }
1335
-
1336
-    /**
1337
-     * Select a SQL database
1338
-     *
1339
-     * @return bool Returns TRUE on success or FALSE on failure.
1340
-     */
1341
-    public function sql_select_db()
1342
-    {
1343
-        if (!$this->isConnected) {
1344
-            $this->connectDB();
1345
-        }
1346
-
1347
-        $ret = $this->link->select_db($this->databaseName);
1348
-        if (!$ret) {
1349
-            GeneralUtility::sysLog(
1350
-                'Could not select MySQL database ' . $this->databaseName . ': ' . $this->sql_error(),
1351
-                'core',
1352
-                GeneralUtility::SYSLOG_SEVERITY_FATAL
1353
-            );
1354
-        }
1355
-        return $ret;
1356
-    }
1357
-
1358
-    /**************************************
1061
+	/**
1062
+	 * Executes query
1063
+	 * MySQLi query() wrapper function
1064
+	 * Beware: Use of this method should be avoided as it is experimentally supported by DBAL. You should consider
1065
+	 * using exec_SELECTquery() and similar methods instead.
1066
+	 *
1067
+	 * @param string $query Query to execute
1068
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
1069
+	 */
1070
+	public function sql_query($query)
1071
+	{
1072
+		$this->logDeprecation();
1073
+		$res = $this->query($query);
1074
+		if ($this->debugOutput) {
1075
+			$this->debug('sql_query', $query);
1076
+		}
1077
+		return $res;
1078
+	}
1079
+
1080
+	/**
1081
+	 * Returns the error status on the last query() execution
1082
+	 *
1083
+	 * @return string MySQLi error string.
1084
+	 */
1085
+	public function sql_error()
1086
+	{
1087
+		$this->logDeprecation();
1088
+		return $this->link->error;
1089
+	}
1090
+
1091
+	/**
1092
+	 * Returns the error number on the last query() execution
1093
+	 *
1094
+	 * @return int MySQLi error number
1095
+	 */
1096
+	public function sql_errno()
1097
+	{
1098
+		$this->logDeprecation();
1099
+		return $this->link->errno;
1100
+	}
1101
+
1102
+	/**
1103
+	 * Returns the number of selected rows.
1104
+	 *
1105
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1106
+	 * @return int Number of resulting rows
1107
+	 */
1108
+	public function sql_num_rows($res)
1109
+	{
1110
+		$this->logDeprecation();
1111
+		if ($this->debug_check_recordset($res)) {
1112
+			return $res->num_rows;
1113
+		} else {
1114
+			return false;
1115
+		}
1116
+	}
1117
+
1118
+	/**
1119
+	 * Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.
1120
+	 * MySQLi fetch_assoc() wrapper function
1121
+	 *
1122
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1123
+	 * @return array|bool Associative array of result row.
1124
+	 */
1125
+	public function sql_fetch_assoc($res)
1126
+	{
1127
+		$this->logDeprecation();
1128
+		if ($this->debug_check_recordset($res)) {
1129
+			$result = $res->fetch_assoc();
1130
+			if ($result === null) {
1131
+				// Needed for compatibility
1132
+				$result = false;
1133
+			}
1134
+			return $result;
1135
+		} else {
1136
+			return false;
1137
+		}
1138
+	}
1139
+
1140
+	/**
1141
+	 * Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.
1142
+	 * The array contains the values in numerical indices.
1143
+	 * MySQLi fetch_row() wrapper function
1144
+	 *
1145
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1146
+	 * @return array|bool Array with result rows.
1147
+	 */
1148
+	public function sql_fetch_row($res)
1149
+	{
1150
+		$this->logDeprecation();
1151
+		if ($this->debug_check_recordset($res)) {
1152
+			$result = $res->fetch_row();
1153
+			if ($result === null) {
1154
+				// Needed for compatibility
1155
+				$result = false;
1156
+			}
1157
+			return $result;
1158
+		} else {
1159
+			return false;
1160
+		}
1161
+	}
1162
+
1163
+	/**
1164
+	 * Free result memory
1165
+	 * free_result() wrapper function
1166
+	 *
1167
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1168
+	 * @return bool Returns TRUE on success or FALSE on failure.
1169
+	 */
1170
+	public function sql_free_result($res)
1171
+	{
1172
+		$this->logDeprecation();
1173
+		if ($this->debug_check_recordset($res) && is_object($res)) {
1174
+			$res->free();
1175
+			return true;
1176
+		} else {
1177
+			return false;
1178
+		}
1179
+	}
1180
+
1181
+	/**
1182
+	 * Get the ID generated from the previous INSERT operation
1183
+	 *
1184
+	 * @return int The uid of the last inserted record.
1185
+	 */
1186
+	public function sql_insert_id()
1187
+	{
1188
+		$this->logDeprecation();
1189
+		return $this->link->insert_id;
1190
+	}
1191
+
1192
+	/**
1193
+	 * Returns the number of rows affected by the last INSERT, UPDATE or DELETE query
1194
+	 *
1195
+	 * @return int Number of rows affected by last query
1196
+	 */
1197
+	public function sql_affected_rows()
1198
+	{
1199
+		return $this->link->affected_rows;
1200
+	}
1201
+
1202
+	/**
1203
+	 * Move internal result pointer
1204
+	 *
1205
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1206
+	 * @param int $seek Seek result number.
1207
+	 * @return bool Returns TRUE on success or FALSE on failure.
1208
+	 */
1209
+	public function sql_data_seek($res, $seek)
1210
+	{
1211
+		$this->logDeprecation();
1212
+		if ($this->debug_check_recordset($res)) {
1213
+			return $res->data_seek($seek);
1214
+		} else {
1215
+			return false;
1216
+		}
1217
+	}
1218
+
1219
+	/**
1220
+	 * Get the type of the specified field in a result
1221
+	 * mysql_field_type() wrapper function
1222
+	 *
1223
+	 * @param bool|\mysqli_result|object $res MySQLi result object / DBAL object
1224
+	 * @param int $pointer Field index.
1225
+	 * @return string Returns the name of the specified field index, or FALSE on error
1226
+	 */
1227
+	public function sql_field_type($res, $pointer)
1228
+	{
1229
+		// mysql_field_type compatibility map
1230
+		// taken from: http://www.php.net/manual/en/mysqli-result.fetch-field-direct.php#89117
1231
+		// Constant numbers see http://php.net/manual/en/mysqli.constants.php
1232
+		$mysql_data_type_hash = [
1233
+			1=>'tinyint',
1234
+			2=>'smallint',
1235
+			3=>'int',
1236
+			4=>'float',
1237
+			5=>'double',
1238
+			7=>'timestamp',
1239
+			8=>'bigint',
1240
+			9=>'mediumint',
1241
+			10=>'date',
1242
+			11=>'time',
1243
+			12=>'datetime',
1244
+			13=>'year',
1245
+			16=>'bit',
1246
+			//252 is currently mapped to all text and blob types (MySQL 5.0.51a)
1247
+			253=>'varchar',
1248
+			254=>'char',
1249
+			246=>'decimal'
1250
+		];
1251
+		if ($this->debug_check_recordset($res)) {
1252
+			$metaInfo = $res->fetch_field_direct($pointer);
1253
+			if ($metaInfo === false) {
1254
+				return false;
1255
+			}
1256
+			return $mysql_data_type_hash[$metaInfo->type];
1257
+		} else {
1258
+			return false;
1259
+		}
1260
+	}
1261
+
1262
+	/**
1263
+	 * Open a (persistent) connection to a MySQL server
1264
+	 *
1265
+	 * @return bool|void
1266
+	 * @throws \RuntimeException
1267
+	 */
1268
+	public function sql_pconnect()
1269
+	{
1270
+		if ($this->isConnected) {
1271
+			return $this->link;
1272
+		}
1273
+
1274
+		if (!extension_loaded('mysqli')) {
1275
+			throw new \RuntimeException(
1276
+				'Database Error: PHP mysqli extension not loaded. This is a must have for TYPO3 CMS!',
1277
+				1271492607
1278
+			);
1279
+		}
1280
+
1281
+		$host = $this->persistentDatabaseConnection
1282
+			? 'p:' . $this->databaseHost
1283
+			: $this->databaseHost;
1284
+
1285
+		// We are not using the TYPO3 CMS shim here as the database parameters in this class
1286
+		// are settable externally. This requires building the connection parameter array
1287
+		// just in time when establishing the connection.
1288
+		$connection = \Doctrine\DBAL\DriverManager::getConnection([
1289
+			'driver' => 'mysqli',
1290
+			'wrapperClass' => Connection::class,
1291
+			'host' => $host,
1292
+			'port' => (int)$this->databasePort,
1293
+			'unix_socket' => $this->databaseSocket,
1294
+			'user' => $this->databaseUsername,
1295
+			'password' => $this->databaseUserPassword,
1296
+			'charset' => $this->connectionCharset,
1297
+		]);
1298
+
1299
+		// Mimic the previous behavior of returning false on connection errors
1300
+		try {
1301
+			/** @var \Doctrine\DBAL\Driver\Mysqli\MysqliConnection $mysqliConnection */
1302
+			$mysqliConnection = $connection->getWrappedConnection();
1303
+			$this->link = $mysqliConnection->getWrappedResourceHandle();
1304
+		} catch (\Doctrine\DBAL\Exception\ConnectionException $exception) {
1305
+			return false;
1306
+		}
1307
+
1308
+		if ($connection->isConnected()) {
1309
+			$this->isConnected = true;
1310
+
1311
+			foreach ($this->initializeCommandsAfterConnect as $command) {
1312
+				if ($this->query($command) === false) {
1313
+					GeneralUtility::sysLog(
1314
+						'Could not initialize DB connection with query "' . $command . '": ' . $this->sql_error(),
1315
+						'core',
1316
+						GeneralUtility::SYSLOG_SEVERITY_ERROR
1317
+					);
1318
+				}
1319
+			}
1320
+			$this->checkConnectionCharset();
1321
+		} else {
1322
+			// @todo This should raise an exception. Would be useful especially to work during installation.
1323
+			$error_msg = $this->link->connect_error;
1324
+			$this->link = null;
1325
+			GeneralUtility::sysLog(
1326
+				'Could not connect to MySQL server ' . $host . ' with user ' . $this->databaseUsername . ': '
1327
+				. $error_msg,
1328
+				'core',
1329
+				GeneralUtility::SYSLOG_SEVERITY_FATAL
1330
+			);
1331
+		}
1332
+
1333
+		return $this->link;
1334
+	}
1335
+
1336
+	/**
1337
+	 * Select a SQL database
1338
+	 *
1339
+	 * @return bool Returns TRUE on success or FALSE on failure.
1340
+	 */
1341
+	public function sql_select_db()
1342
+	{
1343
+		if (!$this->isConnected) {
1344
+			$this->connectDB();
1345
+		}
1346
+
1347
+		$ret = $this->link->select_db($this->databaseName);
1348
+		if (!$ret) {
1349
+			GeneralUtility::sysLog(
1350
+				'Could not select MySQL database ' . $this->databaseName . ': ' . $this->sql_error(),
1351
+				'core',
1352
+				GeneralUtility::SYSLOG_SEVERITY_FATAL
1353
+			);
1354
+		}
1355
+		return $ret;
1356
+	}
1357
+
1358
+	/**************************************
1359 1359
      *
1360 1360
      * SQL admin functions
1361 1361
      * (For use in the Install Tool and Extension Manager)
1362 1362
      *
1363 1363
      **************************************/
1364
-    /**
1365
-     * Listing databases from current MySQL connection. NOTICE: It WILL try to select those databases and thus break selection of current database.
1366
-     * This is only used as a service function in the (1-2-3 process) of the Install Tool.
1367
-     * In any case a lookup should be done in the _DEFAULT handler DBMS then.
1368
-     * Use in Install Tool only!
1369
-     *
1370
-     * @return array Each entry represents a database name
1371
-     * @throws \RuntimeException
1372
-     */
1373
-    public function admin_get_dbs()
1374
-    {
1375
-        $this->logDeprecation();
1376
-        $dbArr = [];
1377
-        $db_list = $this->query('SELECT SCHEMA_NAME FROM information_schema.SCHEMATA');
1378
-        if ($db_list === false) {
1379
-            throw new \RuntimeException(
1380
-                'MySQL Error: Cannot get tablenames: "' . $this->sql_error() . '"!',
1381
-                1378457171
1382
-            );
1383
-        } else {
1384
-            while ($row = $db_list->fetch_object()) {
1385
-                try {
1386
-                    $this->setDatabaseName($row->SCHEMA_NAME);
1387
-                    if ($this->sql_select_db()) {
1388
-                        $dbArr[] = $row->SCHEMA_NAME;
1389
-                    }
1390
-                } catch (\RuntimeException $exception) {
1391
-                    // The exception happens if we cannot connect to the database
1392
-                    // (usually due to missing permissions). This is ok here.
1393
-                    // We catch the exception, skip the database and continue.
1394
-                }
1395
-            }
1396
-        }
1397
-        return $dbArr;
1398
-    }
1399
-
1400
-    /**
1401
-     * Returns the list of tables from the default database, TYPO3_db (quering the DBMS)
1402
-     * In a DBAL this method should 1) look up all tables from the DBMS  of
1403
-     * the _DEFAULT handler and then 2) add all tables *configured* to be managed by other handlers
1404
-     *
1405
-     * @return array Array with tablenames as key and arrays with status information as value
1406
-     */
1407
-    public function admin_get_tables()
1408
-    {
1409
-        $this->logDeprecation();
1410
-        $whichTables = [];
1411
-        $tables_result = $this->query('SHOW TABLE STATUS FROM `' . $this->databaseName . '`');
1412
-        if ($tables_result !== false) {
1413
-            while ($theTable = $tables_result->fetch_assoc()) {
1414
-                $whichTables[$theTable['Name']] = $theTable;
1415
-            }
1416
-            $tables_result->free();
1417
-        }
1418
-        return $whichTables;
1419
-    }
1420
-
1421
-    /**
1422
-     * Returns information about each field in the $table (quering the DBMS)
1423
-     * In a DBAL this should look up the right handler for the table and return compatible information
1424
-     * This function is important not only for the Install Tool but probably for
1425
-     * DBALs as well since they might need to look up table specific information
1426
-     * in order to construct correct queries. In such cases this information should
1427
-     * probably be cached for quick delivery.
1428
-     *
1429
-     * @param string $tableName Table name
1430
-     * @return array Field information in an associative array with fieldname => field row
1431
-     */
1432
-    public function admin_get_fields($tableName)
1433
-    {
1434
-        $this->logDeprecation();
1435
-        $output = [];
1436
-        $columns_res = $this->query('SHOW FULL COLUMNS FROM `' . $tableName . '`');
1437
-        if ($columns_res !== false) {
1438
-            while ($fieldRow = $columns_res->fetch_assoc()) {
1439
-                $output[$fieldRow['Field']] = $fieldRow;
1440
-            }
1441
-            $columns_res->free();
1442
-        }
1443
-        return $output;
1444
-    }
1445
-
1446
-    /**
1447
-     * Returns information about each index key in the $table (quering the DBMS)
1448
-     * In a DBAL this should look up the right handler for the table and return compatible information
1449
-     *
1450
-     * @param string $tableName Table name
1451
-     * @return array Key information in a numeric array
1452
-     */
1453
-    public function admin_get_keys($tableName)
1454
-    {
1455
-        $this->logDeprecation();
1456
-        $output = [];
1457
-        $keyRes = $this->query('SHOW KEYS FROM `' . $tableName . '`');
1458
-        if ($keyRes !== false) {
1459
-            while ($keyRow = $keyRes->fetch_assoc()) {
1460
-                $output[] = $keyRow;
1461
-            }
1462
-            $keyRes->free();
1463
-        }
1464
-        return $output;
1465
-    }
1466
-
1467
-    /**
1468
-     * Returns information about the character sets supported by the current DBM
1469
-     * This function is important not only for the Install Tool but probably for
1470
-     * DBALs as well since they might need to look up table specific information
1471
-     * in order to construct correct queries. In such cases this information should
1472
-     * probably be cached for quick delivery.
1473
-     *
1474
-     * This is used by the Install Tool to convert tables with non-UTF8 charsets
1475
-     * Use in Install Tool only!
1476
-     *
1477
-     * @return array Array with Charset as key and an array of "Charset", "Description", "Default collation", "Maxlen" as values
1478
-     */
1479
-    public function admin_get_charsets()
1480
-    {
1481
-        $this->logDeprecation();
1482
-        $output = [];
1483
-        $columns_res = $this->query('SHOW CHARACTER SET');
1484
-        if ($columns_res !== false) {
1485
-            while ($row = $columns_res->fetch_assoc()) {
1486
-                $output[$row['Charset']] = $row;
1487
-            }
1488
-            $columns_res->free();
1489
-        }
1490
-        return $output;
1491
-    }
1492
-
1493
-    /**
1494
-     * mysqli() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
1495
-     *
1496
-     * @param string $query Query to execute
1497
-     * @return bool|\mysqli_result|object MySQLi result object / DBAL object
1498
-     */
1499
-    public function admin_query($query)
1500
-    {
1501
-        $this->logDeprecation();
1502
-        $res = $this->query($query);
1503
-        if ($this->debugOutput) {
1504
-            $this->debug('admin_query', $query);
1505
-        }
1506
-        return $res;
1507
-    }
1508
-
1509
-    /******************************
1364
+	/**
1365
+	 * Listing databases from current MySQL connection. NOTICE: It WILL try to select those databases and thus break selection of current database.
1366
+	 * This is only used as a service function in the (1-2-3 process) of the Install Tool.
1367
+	 * In any case a lookup should be done in the _DEFAULT handler DBMS then.
1368
+	 * Use in Install Tool only!
1369
+	 *
1370
+	 * @return array Each entry represents a database name
1371
+	 * @throws \RuntimeException
1372
+	 */
1373
+	public function admin_get_dbs()
1374
+	{
1375
+		$this->logDeprecation();
1376
+		$dbArr = [];
1377
+		$db_list = $this->query('SELECT SCHEMA_NAME FROM information_schema.SCHEMATA');
1378
+		if ($db_list === false) {
1379
+			throw new \RuntimeException(
1380
+				'MySQL Error: Cannot get tablenames: "' . $this->sql_error() . '"!',
1381
+				1378457171
1382
+			);
1383
+		} else {
1384
+			while ($row = $db_list->fetch_object()) {
1385
+				try {
1386
+					$this->setDatabaseName($row->SCHEMA_NAME);
1387
+					if ($this->sql_select_db()) {
1388
+						$dbArr[] = $row->SCHEMA_NAME;
1389
+					}
1390
+				} catch (\RuntimeException $exception) {
1391
+					// The exception happens if we cannot connect to the database
1392
+					// (usually due to missing permissions). This is ok here.
1393
+					// We catch the exception, skip the database and continue.
1394
+				}
1395
+			}
1396
+		}
1397
+		return $dbArr;
1398
+	}
1399
+
1400
+	/**
1401
+	 * Returns the list of tables from the default database, TYPO3_db (quering the DBMS)
1402
+	 * In a DBAL this method should 1) look up all tables from the DBMS  of
1403
+	 * the _DEFAULT handler and then 2) add all tables *configured* to be managed by other handlers
1404
+	 *
1405
+	 * @return array Array with tablenames as key and arrays with status information as value
1406
+	 */
1407
+	public function admin_get_tables()
1408
+	{
1409
+		$this->logDeprecation();
1410
+		$whichTables = [];
1411
+		$tables_result = $this->query('SHOW TABLE STATUS FROM `' . $this->databaseName . '`');
1412
+		if ($tables_result !== false) {
1413
+			while ($theTable = $tables_result->fetch_assoc()) {
1414
+				$whichTables[$theTable['Name']] = $theTable;
1415
+			}
1416
+			$tables_result->free();
1417
+		}
1418
+		return $whichTables;
1419
+	}
1420
+
1421
+	/**
1422
+	 * Returns information about each field in the $table (quering the DBMS)
1423
+	 * In a DBAL this should look up the right handler for the table and return compatible information
1424
+	 * This function is important not only for the Install Tool but probably for
1425
+	 * DBALs as well since they might need to look up table specific information
1426
+	 * in order to construct correct queries. In such cases this information should
1427
+	 * probably be cached for quick delivery.
1428
+	 *
1429
+	 * @param string $tableName Table name
1430
+	 * @return array Field information in an associative array with fieldname => field row
1431
+	 */
1432
+	public function admin_get_fields($tableName)
1433
+	{
1434
+		$this->logDeprecation();
1435
+		$output = [];
1436
+		$columns_res = $this->query('SHOW FULL COLUMNS FROM `' . $tableName . '`');
1437
+		if ($columns_res !== false) {
1438
+			while ($fieldRow = $columns_res->fetch_assoc()) {
1439
+				$output[$fieldRow['Field']] = $fieldRow;
1440
+			}
1441
+			$columns_res->free();
1442
+		}
1443
+		return $output;
1444
+	}
1445
+
1446
+	/**
1447
+	 * Returns information about each index key in the $table (quering the DBMS)
1448
+	 * In a DBAL this should look up the right handler for the table and return compatible information
1449
+	 *
1450
+	 * @param string $tableName Table name
1451
+	 * @return array Key information in a numeric array
1452
+	 */
1453
+	public function admin_get_keys($tableName)
1454
+	{
1455
+		$this->logDeprecation();
1456
+		$output = [];
1457
+		$keyRes = $this->query('SHOW KEYS FROM `' . $tableName . '`');
1458
+		if ($keyRes !== false) {
1459
+			while ($keyRow = $keyRes->fetch_assoc()) {
1460
+				$output[] = $keyRow;
1461
+			}
1462
+			$keyRes->free();
1463
+		}
1464
+		return $output;
1465
+	}
1466
+
1467
+	/**
1468
+	 * Returns information about the character sets supported by the current DBM
1469
+	 * This function is important not only for the Install Tool but probably for
1470
+	 * DBALs as well since they might need to look up table specific information
1471
+	 * in order to construct correct queries. In such cases this information should
1472
+	 * probably be cached for quick delivery.
1473
+	 *
1474
+	 * This is used by the Install Tool to convert tables with non-UTF8 charsets
1475
+	 * Use in Install Tool only!
1476
+	 *
1477
+	 * @return array Array with Charset as key and an array of "Charset", "Description", "Default collation", "Maxlen" as values
1478
+	 */
1479
+	public function admin_get_charsets()
1480
+	{
1481
+		$this->logDeprecation();
1482
+		$output = [];
1483
+		$columns_res = $this->query('SHOW CHARACTER SET');
1484
+		if ($columns_res !== false) {
1485
+			while ($row = $columns_res->fetch_assoc()) {
1486
+				$output[$row['Charset']] = $row;
1487
+			}
1488
+			$columns_res->free();
1489
+		}
1490
+		return $output;
1491
+	}
1492
+
1493
+	/**
1494
+	 * mysqli() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
1495
+	 *
1496
+	 * @param string $query Query to execute
1497
+	 * @return bool|\mysqli_result|object MySQLi result object / DBAL object
1498
+	 */
1499
+	public function admin_query($query)
1500
+	{
1501
+		$this->logDeprecation();
1502
+		$res = $this->query($query);
1503
+		if ($this->debugOutput) {
1504
+			$this->debug('admin_query', $query);
1505
+		}
1506
+		return $res;
1507
+	}
1508
+
1509
+	/******************************
1510 1510
      *
1511 1511
      * Connect handling
1512 1512
      *
1513 1513
      ******************************/
1514 1514
 
1515
-    /**
1516
-     * Set database host
1517
-     *
1518
-     * @param string $host
1519
-     */
1520
-    public function setDatabaseHost($host = 'localhost')
1521
-    {
1522
-        $this->disconnectIfConnected();
1523
-        $this->databaseHost = $host;
1524
-    }
1525
-
1526
-    /**
1527
-     * Set database port
1528
-     *
1529
-     * @param int $port
1530
-     */
1531
-    public function setDatabasePort($port = 3306)
1532
-    {
1533
-        $this->disconnectIfConnected();
1534
-        $this->databasePort = (int)$port;
1535
-    }
1536
-
1537
-    /**
1538
-     * Set database socket
1539
-     *
1540
-     * @param string|NULL $socket
1541
-     */
1542
-    public function setDatabaseSocket($socket = null)
1543
-    {
1544
-        $this->disconnectIfConnected();
1545
-        $this->databaseSocket = $socket;
1546
-    }
1547
-
1548
-    /**
1549
-     * Set database name
1550
-     *
1551
-     * @param string $name
1552
-     */
1553
-    public function setDatabaseName($name)
1554
-    {
1555
-        $this->disconnectIfConnected();
1556
-        $this->databaseName = $name;
1557
-    }
1558
-
1559
-    /**
1560
-     * Set database username
1561
-     *
1562
-     * @param string $username
1563
-     */
1564
-    public function setDatabaseUsername($username)
1565
-    {
1566
-        $this->disconnectIfConnected();
1567
-        $this->databaseUsername = $username;
1568
-    }
1569
-
1570
-    /**
1571
-     * Set database password
1572
-     *
1573
-     * @param string $password
1574
-     */
1575
-    public function setDatabasePassword($password)
1576
-    {
1577
-        $this->disconnectIfConnected();
1578
-        $this->databaseUserPassword = $password;
1579
-    }
1580
-
1581
-    /**
1582
-     * Set persistent database connection
1583
-     *
1584
-     * @param bool $persistentDatabaseConnection
1585
-     * @see http://php.net/manual/de/mysqli.persistconns.php
1586
-     */
1587
-    public function setPersistentDatabaseConnection($persistentDatabaseConnection)
1588
-    {
1589
-        $this->disconnectIfConnected();
1590
-        $this->persistentDatabaseConnection = (bool)$persistentDatabaseConnection;
1591
-    }
1592
-
1593
-    /**
1594
-     * Set connection compression. Might be an advantage, if SQL server is not on localhost
1595
-     *
1596
-     * @param bool $connectionCompression TRUE if connection should be compressed
1597
-     */
1598
-    public function setConnectionCompression($connectionCompression)
1599
-    {
1600
-        $this->disconnectIfConnected();
1601
-        $this->connectionCompression = (bool)$connectionCompression;
1602
-    }
1603
-
1604
-    /**
1605
-     * Set commands to be fired after connection was established
1606
-     *
1607
-     * @param array $commands List of SQL commands to be executed after connect
1608
-     */
1609
-    public function setInitializeCommandsAfterConnect(array $commands)
1610
-    {
1611
-        $this->disconnectIfConnected();
1612
-        $this->initializeCommandsAfterConnect = $commands;
1613
-    }
1614
-
1615
-    /**
1616
-     * Set the charset that should be used for the MySQL connection.
1617
-     * The given value will be passed on to mysqli_set_charset().
1618
-     *
1619
-     * The default value of this setting is utf8.
1620
-     *
1621
-     * @param string $connectionCharset The connection charset that will be passed on to mysqli_set_charset() when connecting the database. Default is utf8.
1622
-     */
1623
-    public function setConnectionCharset($connectionCharset = 'utf8')
1624
-    {
1625
-        $this->disconnectIfConnected();
1626
-        $this->connectionCharset = $connectionCharset;
1627
-    }
1628
-
1629
-    /**
1630
-     * Connects to database for TYPO3 sites:
1631
-     *
1632
-     * @throws \RuntimeException
1633
-     * @throws \UnexpectedValueException
1634
-     */
1635
-    public function connectDB()
1636
-    {
1637
-        $this->logDeprecation();
1638
-        // Early return if connected already
1639
-        if ($this->isConnected) {
1640
-            return;
1641
-        }
1642
-
1643
-        if (!$this->databaseName) {
1644
-            throw new \RuntimeException(
1645
-                'TYPO3 Fatal Error: No database selected!',
1646
-                1270853882
1647
-            );
1648
-        }
1649
-
1650
-        if ($this->sql_pconnect()) {
1651
-            if (!$this->sql_select_db()) {
1652
-                throw new \RuntimeException(
1653
-                    'TYPO3 Fatal Error: Cannot connect to the current database, "' . $this->databaseName . '"!',
1654
-                    1270853883
1655
-                );
1656
-            }
1657
-        } else {
1658
-            throw new \RuntimeException(
1659
-                'TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!',
1660
-                1270853884
1661
-            );
1662
-        }
1663
-
1664
-        // Prepare user defined objects (if any) for hooks which extend query methods
1665
-        $this->preProcessHookObjects = [];
1666
-        $this->postProcessHookObjects = [];
1667
-        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'])) {
1668
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'] as $className) {
1669
-                $hookObject = GeneralUtility::makeInstance($className);
1670
-                if (!(
1671
-                    $hookObject instanceof PreProcessQueryHookInterface
1672
-                    || $hookObject instanceof PostProcessQueryHookInterface
1673
-                )) {
1674
-                    throw new \UnexpectedValueException(
1675
-                        '$hookObject must either implement interface TYPO3\\CMS\\Typo3DbLegacy\\Database\\PreProcessQueryHookInterface or interface TYPO3\\CMS\\Typo3DbLegacy\\Database\\PostProcessQueryHookInterface',
1676
-                        1299158548
1677
-                    );
1678
-                }
1679
-                if ($hookObject instanceof PreProcessQueryHookInterface) {
1680
-                    $this->preProcessHookObjects[] = $hookObject;
1681
-                }
1682
-                if ($hookObject instanceof PostProcessQueryHookInterface) {
1683
-                    $this->postProcessHookObjects[] = $hookObject;
1684
-                }
1685
-            }
1686
-        }
1687
-    }
1688
-
1689
-    /**
1690
-     * Checks if database is connected
1691
-     *
1692
-     * @return bool
1693
-     */
1694
-    public function isConnected()
1695
-    {
1696
-        // We think we're still connected
1697
-        if ($this->isConnected) {
1698
-            // Check if this is really the case or if the database server has gone away for some reason
1699
-            // Using mysqlnd ping() does not reconnect (which we would not want anyway since charset etc would not be reinitialized that way)
1700
-            $this->isConnected = $this->link->ping();
1701
-        }
1702
-        return $this->isConnected;
1703
-    }
1704
-
1705
-    /**
1706
-     * Checks if the current connection character set has the same value
1707
-     * as the connectionCharset variable.
1708
-     *
1709
-     * To determine the character set these MySQL session variables are
1710
-     * checked: character_set_client, character_set_results and
1711
-     * character_set_connection.
1712
-     *
1713
-     * If the character set does not match or if the session variables
1714
-     * can not be read a RuntimeException is thrown.
1715
-     *
1716
-     * @throws \RuntimeException
1717
-     */
1718
-    protected function checkConnectionCharset()
1719
-    {
1720
-        $sessionResult = $this->sql_query('SHOW SESSION VARIABLES LIKE \'character_set%\'');
1721
-
1722
-        if ($sessionResult === false) {
1723
-            GeneralUtility::sysLog(
1724
-                'Error while retrieving the current charset session variables from the database: ' . $this->sql_error(),
1725
-                'core',
1726
-                GeneralUtility::SYSLOG_SEVERITY_ERROR
1727
-            );
1728
-            throw new \RuntimeException(
1729
-                'TYPO3 Fatal Error: Could not determine the current charset of the database.',
1730
-                1381847136
1731
-            );
1732
-        }
1733
-
1734
-        $charsetVariables = [];
1735
-        while (($row = $this->sql_fetch_row($sessionResult)) !== false) {
1736
-            $variableName = $row[0];
1737
-            $variableValue = $row[1];
1738
-            $charsetVariables[$variableName] = $variableValue;
1739
-        }
1740
-        $this->sql_free_result($sessionResult);
1741
-
1742
-        // These variables are set with the "Set names" command which was
1743
-        // used in the past. This is why we check them.
1744
-        $charsetRequiredVariables = [
1745
-            'character_set_client',
1746
-            'character_set_results',
1747
-            'character_set_connection',
1748
-        ];
1749
-
1750
-        $hasValidCharset = true;
1751
-        foreach ($charsetRequiredVariables as $variableName) {
1752
-            if (empty($charsetVariables[$variableName])) {
1753
-                GeneralUtility::sysLog(
1754
-                    'A required session variable is missing in the current MySQL connection: ' . $variableName,
1755
-                    'core',
1756
-                    GeneralUtility::SYSLOG_SEVERITY_ERROR
1757
-                );
1758
-                throw new \RuntimeException(
1759
-                    'TYPO3 Fatal Error: Could not determine the value of the database session variable: ' . $variableName,
1760
-                    1381847779
1761
-                );
1762
-            }
1763
-
1764
-            if ($charsetVariables[$variableName] !== $this->connectionCharset) {
1765
-                $hasValidCharset = false;
1766
-                break;
1767
-            }
1768
-        }
1769
-
1770
-        if (!$hasValidCharset) {
1771
-            throw new \RuntimeException(
1772
-                'It looks like the character set ' . $this->connectionCharset . ' is not used for this connection even though it is configured as connection charset. ' .
1773
-                'This TYPO3 installation is using the $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\'] property with the following value: "' .
1774
-                $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'] . '". Please make sure that this command does not overwrite the configured charset. ' .
1775
-                'Please note that for the TYPO3 database everything other than utf8 is unsupported since version 4.7.',
1776
-                1389697515
1777
-            );
1778
-        }
1779
-    }
1780
-
1781
-    /**
1782
-     * Disconnect from database if connected
1783
-     */
1784
-    protected function disconnectIfConnected()
1785
-    {
1786
-        if ($this->isConnected) {
1787
-            $this->link->close();
1788
-            $this->isConnected = false;
1789
-        }
1790
-    }
1791
-
1792
-    /**
1793
-     * Returns current database handle
1794
-     *
1795
-     * @return \mysqli|NULL
1796
-     */
1797
-    public function getDatabaseHandle()
1798
-    {
1799
-        $this->logDeprecation();
1800
-        return $this->link;
1801
-    }
1802
-
1803
-    /**
1804
-     * Set current database handle, usually \mysqli
1805
-     *
1806
-     * @param \mysqli $handle
1807
-     */
1808
-    public function setDatabaseHandle($handle)
1809
-    {
1810
-        $this->link = $handle;
1811
-    }
1812
-
1813
-    /**
1814
-     * Get the MySQL server version
1815
-     *
1816
-     * @return string
1817
-     */
1818
-    public function getServerVersion()
1819
-    {
1820
-        $this->logDeprecation();
1821
-        return $this->link->server_info;
1822
-    }
1823
-
1824
-    /******************************
1515
+	/**
1516
+	 * Set database host
1517
+	 *
1518
+	 * @param string $host
1519
+	 */
1520
+	public function setDatabaseHost($host = 'localhost')
1521
+	{
1522
+		$this->disconnectIfConnected();
1523
+		$this->databaseHost = $host;
1524
+	}
1525
+
1526
+	/**
1527
+	 * Set database port
1528
+	 *
1529
+	 * @param int $port
1530
+	 */
1531
+	public function setDatabasePort($port = 3306)
1532
+	{
1533
+		$this->disconnectIfConnected();
1534
+		$this->databasePort = (int)$port;
1535
+	}
1536
+
1537
+	/**
1538
+	 * Set database socket
1539
+	 *
1540
+	 * @param string|NULL $socket
1541
+	 */
1542
+	public function setDatabaseSocket($socket = null)
1543
+	{
1544
+		$this->disconnectIfConnected();
1545
+		$this->databaseSocket = $socket;
1546
+	}
1547
+
1548
+	/**
1549
+	 * Set database name
1550
+	 *
1551
+	 * @param string $name
1552
+	 */
1553
+	public function setDatabaseName($name)
1554
+	{
1555
+		$this->disconnectIfConnected();
1556
+		$this->databaseName = $name;
1557
+	}
1558
+
1559
+	/**
1560
+	 * Set database username
1561
+	 *
1562
+	 * @param string $username
1563
+	 */
1564
+	public function setDatabaseUsername($username)
1565
+	{
1566
+		$this->disconnectIfConnected();
1567
+		$this->databaseUsername = $username;
1568
+	}
1569
+
1570
+	/**
1571
+	 * Set database password
1572
+	 *
1573
+	 * @param string $password
1574
+	 */
1575
+	public function setDatabasePassword($password)
1576
+	{
1577
+		$this->disconnectIfConnected();
1578
+		$this->databaseUserPassword = $password;
1579
+	}
1580
+
1581
+	/**
1582
+	 * Set persistent database connection
1583
+	 *
1584
+	 * @param bool $persistentDatabaseConnection
1585
+	 * @see http://php.net/manual/de/mysqli.persistconns.php
1586
+	 */
1587
+	public function setPersistentDatabaseConnection($persistentDatabaseConnection)
1588
+	{
1589
+		$this->disconnectIfConnected();
1590
+		$this->persistentDatabaseConnection = (bool)$persistentDatabaseConnection;
1591
+	}
1592
+
1593
+	/**
1594
+	 * Set connection compression. Might be an advantage, if SQL server is not on localhost
1595
+	 *
1596
+	 * @param bool $connectionCompression TRUE if connection should be compressed
1597
+	 */
1598
+	public function setConnectionCompression($connectionCompression)
1599
+	{
1600
+		$this->disconnectIfConnected();
1601
+		$this->connectionCompression = (bool)$connectionCompression;
1602
+	}
1603
+
1604
+	/**
1605
+	 * Set commands to be fired after connection was established
1606
+	 *
1607
+	 * @param array $commands List of SQL commands to be executed after connect
1608
+	 */
1609
+	public function setInitializeCommandsAfterConnect(array $commands)
1610
+	{
1611
+		$this->disconnectIfConnected();
1612
+		$this->initializeCommandsAfterConnect = $commands;
1613
+	}
1614
+
1615
+	/**
1616
+	 * Set the charset that should be used for the MySQL connection.
1617
+	 * The given value will be passed on to mysqli_set_charset().
1618
+	 *
1619
+	 * The default value of this setting is utf8.
1620
+	 *
1621
+	 * @param string $connectionCharset The connection charset that will be passed on to mysqli_set_charset() when connecting the database. Default is utf8.
1622
+	 */
1623
+	public function setConnectionCharset($connectionCharset = 'utf8')
1624
+	{
1625
+		$this->disconnectIfConnected();
1626
+		$this->connectionCharset = $connectionCharset;
1627
+	}
1628
+
1629
+	/**
1630
+	 * Connects to database for TYPO3 sites:
1631
+	 *
1632
+	 * @throws \RuntimeException
1633
+	 * @throws \UnexpectedValueException
1634
+	 */
1635
+	public function connectDB()
1636
+	{
1637
+		$this->logDeprecation();
1638
+		// Early return if connected already
1639
+		if ($this->isConnected) {
1640
+			return;
1641
+		}
1642
+
1643
+		if (!$this->databaseName) {
1644
+			throw new \RuntimeException(
1645
+				'TYPO3 Fatal Error: No database selected!',
1646
+				1270853882
1647
+			);
1648
+		}
1649
+
1650
+		if ($this->sql_pconnect()) {
1651
+			if (!$this->sql_select_db()) {
1652
+				throw new \RuntimeException(
1653
+					'TYPO3 Fatal Error: Cannot connect to the current database, "' . $this->databaseName . '"!',
1654
+					1270853883
1655
+				);
1656
+			}
1657
+		} else {
1658
+			throw new \RuntimeException(
1659
+				'TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!',
1660
+				1270853884
1661
+			);
1662
+		}
1663
+
1664
+		// Prepare user defined objects (if any) for hooks which extend query methods
1665
+		$this->preProcessHookObjects = [];
1666
+		$this->postProcessHookObjects = [];
1667
+		if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'])) {
1668
+			foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'] as $className) {
1669
+				$hookObject = GeneralUtility::makeInstance($className);
1670
+				if (!(
1671
+					$hookObject instanceof PreProcessQueryHookInterface
1672
+					|| $hookObject instanceof PostProcessQueryHookInterface
1673
+				)) {
1674
+					throw new \UnexpectedValueException(
1675
+						'$hookObject must either implement interface TYPO3\\CMS\\Typo3DbLegacy\\Database\\PreProcessQueryHookInterface or interface TYPO3\\CMS\\Typo3DbLegacy\\Database\\PostProcessQueryHookInterface',
1676
+						1299158548
1677
+					);
1678
+				}
1679
+				if ($hookObject instanceof PreProcessQueryHookInterface) {
1680
+					$this->preProcessHookObjects[] = $hookObject;
1681
+				}
1682
+				if ($hookObject instanceof PostProcessQueryHookInterface) {
1683
+					$this->postProcessHookObjects[] = $hookObject;
1684
+				}
1685
+			}
1686
+		}
1687
+	}
1688
+
1689
+	/**
1690
+	 * Checks if database is connected
1691
+	 *
1692
+	 * @return bool
1693
+	 */
1694
+	public function isConnected()
1695
+	{
1696
+		// We think we're still connected
1697
+		if ($this->isConnected) {
1698
+			// Check if this is really the case or if the database server has gone away for some reason
1699
+			// Using mysqlnd ping() does not reconnect (which we would not want anyway since charset etc would not be reinitialized that way)
1700
+			$this->isConnected = $this->link->ping();
1701
+		}
1702
+		return $this->isConnected;
1703
+	}
1704
+
1705
+	/**
1706
+	 * Checks if the current connection character set has the same value
1707
+	 * as the connectionCharset variable.
1708
+	 *
1709
+	 * To determine the character set these MySQL session variables are
1710
+	 * checked: character_set_client, character_set_results and
1711
+	 * character_set_connection.
1712
+	 *
1713
+	 * If the character set does not match or if the session variables
1714
+	 * can not be read a RuntimeException is thrown.
1715
+	 *
1716
+	 * @throws \RuntimeException
1717
+	 */
1718
+	protected function checkConnectionCharset()
1719
+	{
1720
+		$sessionResult = $this->sql_query('SHOW SESSION VARIABLES LIKE \'character_set%\'');
1721
+
1722
+		if ($sessionResult === false) {
1723
+			GeneralUtility::sysLog(
1724
+				'Error while retrieving the current charset session variables from the database: ' . $this->sql_error(),
1725
+				'core',
1726
+				GeneralUtility::SYSLOG_SEVERITY_ERROR
1727
+			);
1728
+			throw new \RuntimeException(
1729
+				'TYPO3 Fatal Error: Could not determine the current charset of the database.',
1730
+				1381847136
1731
+			);
1732
+		}
1733
+
1734
+		$charsetVariables = [];
1735
+		while (($row = $this->sql_fetch_row($sessionResult)) !== false) {
1736
+			$variableName = $row[0];
1737
+			$variableValue = $row[1];
1738
+			$charsetVariables[$variableName] = $variableValue;
1739
+		}
1740
+		$this->sql_free_result($sessionResult);
1741
+
1742
+		// These variables are set with the "Set names" command which was
1743
+		// used in the past. This is why we check them.
1744
+		$charsetRequiredVariables = [
1745
+			'character_set_client',
1746
+			'character_set_results',
1747
+			'character_set_connection',
1748
+		];
1749
+
1750
+		$hasValidCharset = true;
1751
+		foreach ($charsetRequiredVariables as $variableName) {
1752
+			if (empty($charsetVariables[$variableName])) {
1753
+				GeneralUtility::sysLog(
1754
+					'A required session variable is missing in the current MySQL connection: ' . $variableName,
1755
+					'core',
1756
+					GeneralUtility::SYSLOG_SEVERITY_ERROR
1757
+				);
1758
+				throw new \RuntimeException(
1759
+					'TYPO3 Fatal Error: Could not determine the value of the database session variable: ' . $variableName,
1760
+					1381847779
1761
+				);
1762
+			}
1763
+
1764
+			if ($charsetVariables[$variableName] !== $this->connectionCharset) {
1765
+				$hasValidCharset = false;
1766
+				break;
1767
+			}
1768
+		}
1769
+
1770
+		if (!$hasValidCharset) {
1771
+			throw new \RuntimeException(
1772
+				'It looks like the character set ' . $this->connectionCharset . ' is not used for this connection even though it is configured as connection charset. ' .
1773
+				'This TYPO3 installation is using the $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\'] property with the following value: "' .
1774
+				$GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'] . '". Please make sure that this command does not overwrite the configured charset. ' .
1775
+				'Please note that for the TYPO3 database everything other than utf8 is unsupported since version 4.7.',
1776
+				1389697515
1777
+			);
1778
+		}
1779
+	}
1780
+
1781
+	/**
1782
+	 * Disconnect from database if connected
1783
+	 */
1784
+	protected function disconnectIfConnected()
1785
+	{
1786
+		if ($this->isConnected) {
1787
+			$this->link->close();
1788
+			$this->isConnected = false;
1789
+		}
1790
+	}
1791
+
1792
+	/**
1793
+	 * Returns current database handle
1794
+	 *
1795
+	 * @return \mysqli|NULL
1796
+	 */
1797
+	public function getDatabaseHandle()
1798
+	{
1799
+		$this->logDeprecation();
1800
+		return $this->link;
1801
+	}
1802
+
1803
+	/**
1804
+	 * Set current database handle, usually \mysqli
1805
+	 *
1806
+	 * @param \mysqli $handle
1807
+	 */
1808
+	public function setDatabaseHandle($handle)
1809
+	{
1810
+		$this->link = $handle;
1811
+	}
1812
+
1813
+	/**
1814
+	 * Get the MySQL server version
1815
+	 *
1816
+	 * @return string
1817
+	 */
1818
+	public function getServerVersion()
1819
+	{
1820
+		$this->logDeprecation();
1821
+		return $this->link->server_info;
1822
+	}
1823
+
1824
+	/******************************
1825 1825
      *
1826 1826
      * Debugging
1827 1827
      *
1828 1828
      ******************************/
1829
-    /**
1830
-     * Debug function: Outputs error if any
1831
-     *
1832
-     * @param string $func Function calling debug()
1833
-     * @param string $query Last query if not last built query
1834
-     */
1835
-    public function debug($func, $query = '')
1836
-    {
1837
-        $this->logDeprecation();
1838
-        $error = $this->sql_error();
1839
-        if ($error || (int)$this->debugOutput === 2) {
1840
-            \TYPO3\CMS\Core\Utility\DebugUtility::debug(
1841
-                [
1842
-                    'caller' => \Fab\Vidi\Database\DatabaseConnection::class . '::' . $func,
1843
-                    'ERROR' => $error,
1844
-                    'lastBuiltQuery' => $query ? $query : $this->debug_lastBuiltQuery,
1845
-                    'debug_backtrace' => \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail()
1846
-                ],
1847
-                $func,
1848
-                is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debug'])
1849
-                    ? ''
1850
-                    : 'DB Error'
1851
-            );
1852
-        }
1853
-    }
1854
-
1855
-    /**
1856
-     * Checks if record set is valid and writes debugging information into devLog if not.
1857
-     *
1858
-     * @param bool|\mysqli_result|object MySQLi result object / DBAL object
1859
-     * @return bool TRUE if the  record set is valid, FALSE otherwise
1860
-     */
1861
-    public function debug_check_recordset($res)
1862
-    {
1863
-        $this->logDeprecation();
1864
-        if ($res !== false && $res !== null) {
1865
-            return true;
1866
-        }
1867
-        $trace = debug_backtrace(0);
1868
-        array_shift($trace);
1869
-        $msg = 'Invalid database result detected: function TYPO3\\CMS\\Typo3DbLegacy\\Database\\DatabaseConnection->'
1870
-            . $trace[0]['function'] . ' called from file ' . substr($trace[0]['file'], (strlen(PATH_site) + 2))
1871
-            . ' in line ' . $trace[0]['line'] . '.';
1872
-        GeneralUtility::sysLog(
1873
-            $msg . ' Use a devLog extension to get more details.',
1874
-            'core',
1875
-            GeneralUtility::SYSLOG_SEVERITY_ERROR
1876
-        );
1877
-        // Send to devLog if enabled
1878
-        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'])) {
1879
-            $debugLogData = [
1880
-                'SQL Error' => $this->sql_error(),
1881
-                'Backtrace' => $trace
1882
-            ];
1883
-            if ($this->debug_lastBuiltQuery) {
1884
-                $debugLogData = ['SQL Query' => $this->debug_lastBuiltQuery] + $debugLogData;
1885
-            }
1886
-            GeneralUtility::devLog($msg, 'Core/t3lib_db', 3, $debugLogData);
1887
-        }
1888
-        return false;
1889
-    }
1890
-
1891
-    /**
1892
-     * Explain select queries
1893
-     * If $this->explainOutput is set, SELECT queries will be explained here. Only queries with more than one possible result row will be displayed.
1894
-     * The output is either printed as raw HTML output or embedded into the TS admin panel (checkbox must be enabled!)
1895
-     *
1896
-     * @todo Feature is not DBAL-compliant
1897
-     *
1898
-     * @param string $query SQL query
1899
-     * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
1900
-     * @param int $row_count Number of resulting rows
1901
-     * @return bool TRUE if explain was run, FALSE otherwise
1902
-     */
1903
-    protected function explain($query, $from_table, $row_count)
1904
-    {
1905
-        $debugAllowedForIp = GeneralUtility::cmpIP(
1906
-            GeneralUtility::getIndpEnv('REMOTE_ADDR'),
1907
-            $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']
1908
-        );
1909
-        if (
1910
-            (int)$this->explainOutput == 1
1911
-            || ((int)$this->explainOutput == 2 && $debugAllowedForIp)
1912
-        ) {
1913
-            // Raw HTML output
1914
-            $explainMode = 1;
1915
-        } elseif ((int)$this->explainOutput == 3) {
1916
-            // Embed the output into the TS admin panel
1917
-            $explainMode = 2;
1918
-        } else {
1919
-            return false;
1920
-        }
1921
-        $error = $this->sql_error();
1922
-        $trail = \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail();
1923
-        $explain_tables = [];
1924
-        $explain_output = [];
1925
-        $res = $this->sql_query('EXPLAIN ' . $query, $this->link);
1926
-        if (is_a($res, '\\mysqli_result')) {
1927
-            while ($tempRow = $this->sql_fetch_assoc($res)) {
1928
-                $explain_output[] = $tempRow;
1929
-                $explain_tables[] = $tempRow['table'];
1930
-            }
1931
-            $this->sql_free_result($res);
1932
-        }
1933
-        $indices_output = [];
1934
-        // Notice: Rows are skipped if there is only one result, or if no conditions are set
1935
-        if ($explain_output[0]['rows'] > 1 || $explain_output[0]['type'] === 'ALL') {
1936
-            // Only enable output if it's really useful
1937
-            $debug = true;
1938
-            foreach ($explain_tables as $table) {
1939
-                $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
1940
-                $isTable = $this->sql_num_rows($tableRes);
1941
-                if ($isTable) {
1942
-                    $res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
1943
-                    if (is_a($res, '\\mysqli_result')) {
1944
-                        while ($tempRow = $this->sql_fetch_assoc($res)) {
1945
-                            $indices_output[] = $tempRow;
1946
-                        }
1947
-                        $this->sql_free_result($res);
1948
-                    }
1949
-                }
1950
-                $this->sql_free_result($tableRes);
1951
-            }
1952
-        } else {
1953
-            $debug = false;
1954
-        }
1955
-        if ($debug) {
1956
-            if ($explainMode) {
1957
-                $data = [];
1958
-                $data['query'] = $query;
1959
-                $data['trail'] = $trail;
1960
-                $data['row_count'] = $row_count;
1961
-                if ($error) {
1962
-                    $data['error'] = $error;
1963
-                }
1964
-                if (!empty($explain_output)) {
1965
-                    $data['explain'] = $explain_output;
1966
-                }
1967
-                if (!empty($indices_output)) {
1968
-                    $data['indices'] = $indices_output;
1969
-                }
1970
-                if ($explainMode == 1) {
1971
-                    \TYPO3\CMS\Core\Utility\DebugUtility::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
1972
-                } elseif ($explainMode == 2) {
1973
-                    /** @var TimeTracker $timeTracker */
1974
-                    $timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
1975
-                    $timeTracker->setTSselectQuery($data);
1976
-                }
1977
-            }
1978
-            return true;
1979
-        }
1980
-        return false;
1981
-    }
1982
-
1983
-    /**
1984
-     * Serialize destructs current connection
1985
-     *
1986
-     * @return array All protected properties that should be saved
1987
-     */
1988
-    public function __sleep()
1989
-    {
1990
-        $this->disconnectIfConnected();
1991
-        return [
1992
-            'debugOutput',
1993
-            'explainOutput',
1994
-            'databaseHost',
1995
-            'databasePort',
1996
-            'databaseSocket',
1997
-            'databaseName',
1998
-            'databaseUsername',
1999
-            'databaseUserPassword',
2000
-            'persistentDatabaseConnection',
2001
-            'connectionCompression',
2002
-            'initializeCommandsAfterConnect',
2003
-            'default_charset',
2004
-        ];
2005
-    }
2006
-
2007
-    /**
2008
-     * function to call a deprecation log entry (but only once per request / class)
2009
-     */
2010
-    protected function logDeprecation()
2011
-    {
2012
-        if (!$this->deprecationWarningThrown) {
2013
-            $this->deprecationWarningThrown = true;
2014
-            GeneralUtility::deprecationLog('DatabaseConnection a.k.a. $["TYPO3_DB"] has been marked as deprecated in'
2015
-            . ' TYPO3 v8 and will be removed in TYPO3 v9. Please use the newly available ConnectionPool and QueryBuilder'
2016
-            . ' classes.');
2017
-        }
2018
-    }
1829
+	/**
1830
+	 * Debug function: Outputs error if any
1831
+	 *
1832
+	 * @param string $func Function calling debug()
1833
+	 * @param string $query Last query if not last built query
1834
+	 */
1835
+	public function debug($func, $query = '')
1836
+	{
1837
+		$this->logDeprecation();
1838
+		$error = $this->sql_error();
1839
+		if ($error || (int)$this->debugOutput === 2) {
1840
+			\TYPO3\CMS\Core\Utility\DebugUtility::debug(
1841
+				[
1842
+					'caller' => \Fab\Vidi\Database\DatabaseConnection::class . '::' . $func,
1843
+					'ERROR' => $error,
1844
+					'lastBuiltQuery' => $query ? $query : $this->debug_lastBuiltQuery,
1845
+					'debug_backtrace' => \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail()
1846
+				],
1847
+				$func,
1848
+				is_object($GLOBALS['error']) && @is_callable([$GLOBALS['error'], 'debug'])
1849
+					? ''
1850
+					: 'DB Error'
1851
+			);
1852
+		}
1853
+	}
1854
+
1855
+	/**
1856
+	 * Checks if record set is valid and writes debugging information into devLog if not.
1857
+	 *
1858
+	 * @param bool|\mysqli_result|object MySQLi result object / DBAL object
1859
+	 * @return bool TRUE if the  record set is valid, FALSE otherwise
1860
+	 */
1861
+	public function debug_check_recordset($res)
1862
+	{
1863
+		$this->logDeprecation();
1864
+		if ($res !== false && $res !== null) {
1865
+			return true;
1866
+		}
1867
+		$trace = debug_backtrace(0);
1868
+		array_shift($trace);
1869
+		$msg = 'Invalid database result detected: function TYPO3\\CMS\\Typo3DbLegacy\\Database\\DatabaseConnection->'
1870
+			. $trace[0]['function'] . ' called from file ' . substr($trace[0]['file'], (strlen(PATH_site) + 2))
1871
+			. ' in line ' . $trace[0]['line'] . '.';
1872
+		GeneralUtility::sysLog(
1873
+			$msg . ' Use a devLog extension to get more details.',
1874
+			'core',
1875
+			GeneralUtility::SYSLOG_SEVERITY_ERROR
1876
+		);
1877
+		// Send to devLog if enabled
1878
+		if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['devLog'])) {
1879
+			$debugLogData = [
1880
+				'SQL Error' => $this->sql_error(),
1881
+				'Backtrace' => $trace
1882
+			];
1883
+			if ($this->debug_lastBuiltQuery) {
1884
+				$debugLogData = ['SQL Query' => $this->debug_lastBuiltQuery] + $debugLogData;
1885
+			}
1886
+			GeneralUtility::devLog($msg, 'Core/t3lib_db', 3, $debugLogData);
1887
+		}
1888
+		return false;
1889
+	}
1890
+
1891
+	/**
1892
+	 * Explain select queries
1893
+	 * If $this->explainOutput is set, SELECT queries will be explained here. Only queries with more than one possible result row will be displayed.
1894
+	 * The output is either printed as raw HTML output or embedded into the TS admin panel (checkbox must be enabled!)
1895
+	 *
1896
+	 * @todo Feature is not DBAL-compliant
1897
+	 *
1898
+	 * @param string $query SQL query
1899
+	 * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Required value.
1900
+	 * @param int $row_count Number of resulting rows
1901
+	 * @return bool TRUE if explain was run, FALSE otherwise
1902
+	 */
1903
+	protected function explain($query, $from_table, $row_count)
1904
+	{
1905
+		$debugAllowedForIp = GeneralUtility::cmpIP(
1906
+			GeneralUtility::getIndpEnv('REMOTE_ADDR'),
1907
+			$GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']
1908
+		);
1909
+		if (
1910
+			(int)$this->explainOutput == 1
1911
+			|| ((int)$this->explainOutput == 2 && $debugAllowedForIp)
1912
+		) {
1913
+			// Raw HTML output
1914
+			$explainMode = 1;
1915
+		} elseif ((int)$this->explainOutput == 3) {
1916
+			// Embed the output into the TS admin panel
1917
+			$explainMode = 2;
1918
+		} else {
1919
+			return false;
1920
+		}
1921
+		$error = $this->sql_error();
1922
+		$trail = \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail();
1923
+		$explain_tables = [];
1924
+		$explain_output = [];
1925
+		$res = $this->sql_query('EXPLAIN ' . $query, $this->link);
1926
+		if (is_a($res, '\\mysqli_result')) {
1927
+			while ($tempRow = $this->sql_fetch_assoc($res)) {
1928
+				$explain_output[] = $tempRow;
1929
+				$explain_tables[] = $tempRow['table'];
1930
+			}
1931
+			$this->sql_free_result($res);
1932
+		}
1933
+		$indices_output = [];
1934
+		// Notice: Rows are skipped if there is only one result, or if no conditions are set
1935
+		if ($explain_output[0]['rows'] > 1 || $explain_output[0]['type'] === 'ALL') {
1936
+			// Only enable output if it's really useful
1937
+			$debug = true;
1938
+			foreach ($explain_tables as $table) {
1939
+				$tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
1940
+				$isTable = $this->sql_num_rows($tableRes);
1941
+				if ($isTable) {
1942
+					$res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
1943
+					if (is_a($res, '\\mysqli_result')) {
1944
+						while ($tempRow = $this->sql_fetch_assoc($res)) {
1945
+							$indices_output[] = $tempRow;
1946
+						}
1947
+						$this->sql_free_result($res);
1948
+					}
1949
+				}
1950
+				$this->sql_free_result($tableRes);
1951
+			}
1952
+		} else {
1953
+			$debug = false;
1954
+		}
1955
+		if ($debug) {
1956
+			if ($explainMode) {
1957
+				$data = [];
1958
+				$data['query'] = $query;
1959
+				$data['trail'] = $trail;
1960
+				$data['row_count'] = $row_count;
1961
+				if ($error) {
1962
+					$data['error'] = $error;
1963
+				}
1964
+				if (!empty($explain_output)) {
1965
+					$data['explain'] = $explain_output;
1966
+				}
1967
+				if (!empty($indices_output)) {
1968
+					$data['indices'] = $indices_output;
1969
+				}
1970
+				if ($explainMode == 1) {
1971
+					\TYPO3\CMS\Core\Utility\DebugUtility::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
1972
+				} elseif ($explainMode == 2) {
1973
+					/** @var TimeTracker $timeTracker */
1974
+					$timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
1975
+					$timeTracker->setTSselectQuery($data);
1976
+				}
1977
+			}
1978
+			return true;
1979
+		}
1980
+		return false;
1981
+	}
1982
+
1983
+	/**
1984
+	 * Serialize destructs current connection
1985
+	 *
1986
+	 * @return array All protected properties that should be saved
1987
+	 */
1988
+	public function __sleep()
1989
+	{
1990
+		$this->disconnectIfConnected();
1991
+		return [
1992
+			'debugOutput',
1993
+			'explainOutput',
1994
+			'databaseHost',
1995
+			'databasePort',
1996
+			'databaseSocket',
1997
+			'databaseName',
1998
+			'databaseUsername',
1999
+			'databaseUserPassword',
2000
+			'persistentDatabaseConnection',
2001
+			'connectionCompression',
2002
+			'initializeCommandsAfterConnect',
2003
+			'default_charset',
2004
+		];
2005
+	}
2006
+
2007
+	/**
2008
+	 * function to call a deprecation log entry (but only once per request / class)
2009
+	 */
2010
+	protected function logDeprecation()
2011
+	{
2012
+		if (!$this->deprecationWarningThrown) {
2013
+			$this->deprecationWarningThrown = true;
2014
+			GeneralUtility::deprecationLog('DatabaseConnection a.k.a. $["TYPO3_DB"] has been marked as deprecated in'
2015
+			. ' TYPO3 v8 and will be removed in TYPO3 v9. Please use the newly available ConnectionPool and QueryBuilder'
2016
+			. ' classes.');
2017
+		}
2018
+	}
2019 2019
 }
Please login to merge, or discard this patch.
Spacing   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
                     $firstRecord = false;
388 388
                     if (!array_key_exists($uidIndexField, $record)) {
389 389
                         $this->sql_free_result($res);
390
-                        throw new \InvalidArgumentException('The given $uidIndexField "' . $uidIndexField . '" is not available in the result.', 1432933855);
390
+                        throw new \InvalidArgumentException('The given $uidIndexField "'.$uidIndexField.'" is not available in the result.', 1432933855);
391 391
                     }
392 392
                 }
393 393
                 $output[$record[$uidIndexField]] = $record;
@@ -439,7 +439,7 @@  discard block
 block discarded – undo
439 439
     {
440 440
         $this->logDeprecation();
441 441
         $count = false;
442
-        $resultSet = $this->exec_SELECTquery('COUNT(' . $field . ')', $table, $where);
442
+        $resultSet = $this->exec_SELECTquery('COUNT('.$field.')', $table, $where);
443 443
         if ($resultSet !== false) {
444 444
             list($count) = $this->sql_fetch_row($resultSet);
445 445
             $count = (int)$count;
@@ -511,7 +511,7 @@  discard block
 block discarded – undo
511 511
         // Quote and escape values
512 512
         $fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
513 513
         // Build query
514
-        $query = 'INSERT INTO ' . $table . ' (' . implode(',', array_keys($fields_values)) . ') VALUES ' . '(' . implode(',', $fields_values) . ')';
514
+        $query = 'INSERT INTO '.$table.' ('.implode(',', array_keys($fields_values)).') VALUES '.'('.implode(',', $fields_values).')';
515 515
         // Return query
516 516
         if ($this->debugOutput || $this->store_lastBuiltQuery) {
517 517
             $this->debug_lastBuiltQuery = $query;
@@ -541,12 +541,12 @@  discard block
 block discarded – undo
541 541
             $hookObject->INSERTmultipleRows_preProcessAction($table, $fields, $rows, $no_quote_fields, $this);
542 542
         }
543 543
         // Build query
544
-        $query = 'INSERT INTO ' . $table . ' (' . implode(', ', $fields) . ') VALUES ';
544
+        $query = 'INSERT INTO '.$table.' ('.implode(', ', $fields).') VALUES ';
545 545
         $rowSQL = [];
546 546
         foreach ($rows as $row) {
547 547
             // Quote and escape values
548 548
             $row = $this->fullQuoteArray($row, $table, $no_quote_fields);
549
-            $rowSQL[] = '(' . implode(', ', $row) . ')';
549
+            $rowSQL[] = '('.implode(', ', $row).')';
550 550
         }
551 551
         $query .= implode(', ', $rowSQL);
552 552
         // Return query
@@ -582,11 +582,11 @@  discard block
 block discarded – undo
582 582
                 // Quote and escape values
583 583
                 $nArr = $this->fullQuoteArray($fields_values, $table, $no_quote_fields, true);
584 584
                 foreach ($nArr as $k => $v) {
585
-                    $fields[] = $k . '=' . $v;
585
+                    $fields[] = $k.'='.$v;
586 586
                 }
587 587
             }
588 588
             // Build query
589
-            $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) . ((string)$where !== '' ? ' WHERE ' . $where : '');
589
+            $query = 'UPDATE '.$table.' SET '.implode(',', $fields).((string)$where !== '' ? ' WHERE '.$where : '');
590 590
             if ($this->debugOutput || $this->store_lastBuiltQuery) {
591 591
                 $this->debug_lastBuiltQuery = $query;
592 592
             }
@@ -613,7 +613,7 @@  discard block
 block discarded – undo
613 613
                 $hookObject->DELETEquery_preProcessAction($table, $where, $this);
614 614
             }
615 615
             // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
616
-            $query = 'DELETE FROM ' . $table . ((string)$where !== '' ? ' WHERE ' . $where : '');
616
+            $query = 'DELETE FROM '.$table.((string)$where !== '' ? ' WHERE '.$where : '');
617 617
             if ($this->debugOutput || $this->store_lastBuiltQuery) {
618 618
                 $this->debug_lastBuiltQuery = $query;
619 619
             }
@@ -643,13 +643,13 @@  discard block
 block discarded – undo
643 643
         }
644 644
         // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
645 645
         // Build basic query
646
-        $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
646
+        $query = 'SELECT '.$select_fields.' FROM '.$from_table.((string)$where_clause !== '' ? ' WHERE '.$where_clause : '');
647 647
         // Group by
648
-        $query .= (string)$groupBy !== '' ? ' GROUP BY ' . $groupBy : '';
648
+        $query .= (string)$groupBy !== '' ? ' GROUP BY '.$groupBy : '';
649 649
         // Order by
650
-        $query .= (string)$orderBy !== '' ? ' ORDER BY ' . $orderBy : '';
650
+        $query .= (string)$orderBy !== '' ? ' ORDER BY '.$orderBy : '';
651 651
         // Group by
652
-        $query .= (string)$limit !== '' ? ' LIMIT ' . $limit : '';
652
+        $query .= (string)$limit !== '' ? ' LIMIT '.$limit : '';
653 653
         // Return query
654 654
         if ($this->debugOutput || $this->store_lastBuiltQuery) {
655 655
             $this->debug_lastBuiltQuery = $query;
@@ -671,7 +671,7 @@  discard block
 block discarded – undo
671 671
         $this->logDeprecation();
672 672
         // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
673 673
         // Build basic query:
674
-        $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table . ((string)$where_clause !== '' ? ' WHERE ' . $where_clause : '');
674
+        $query = 'SELECT '.$select_fields.' FROM '.$from_table.((string)$where_clause !== '' ? ' WHERE '.$where_clause : '');
675 675
         // Return query
676 676
         if ($this->debugOutput || $this->store_lastBuiltQuery) {
677 677
             $this->debug_lastBuiltQuery = $query;
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
         }
719 719
         // Table should be "SQL-injection-safe" when supplied to this function
720 720
         // Build basic query:
721
-        $query = 'TRUNCATE TABLE ' . $table;
721
+        $query = 'TRUNCATE TABLE '.$table;
722 722
         // Return query:
723 723
         if ($this->debugOutput || $this->store_lastBuiltQuery) {
724 724
             $this->debug_lastBuiltQuery = $query;
@@ -749,7 +749,7 @@  discard block
 block discarded – undo
749 749
             throw new \InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !', 1294585862);
750 750
         }
751 751
         $pattern = $this->quoteStr($value, $table);
752
-        $where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
752
+        $where = 'FIND_IN_SET(\''.$pattern.'\','.$field.')';
753 753
         return $where;
754 754
     }
755 755
 
@@ -775,10 +775,10 @@  discard block
 block discarded – undo
775 775
 
776 776
         $queryParts = [];
777 777
         foreach ($searchWords as $sw) {
778
-            $like = ' LIKE \'%' . $this->quoteStr($this->escapeStrForLike($sw, $table), $table) . '%\'';
779
-            $queryParts[] = $table . '.' . implode(($like . ' OR ' . $table . '.'), $fields) . $like;
778
+            $like = ' LIKE \'%'.$this->quoteStr($this->escapeStrForLike($sw, $table), $table).'%\'';
779
+            $queryParts[] = $table.'.'.implode(($like.' OR '.$table.'.'), $fields).$like;
780 780
         }
781
-        $query = '(' . implode(') ' . $constraint . ' (', $queryParts) . ')';
781
+        $query = '('.implode(') '.$constraint.' (', $queryParts).')';
782 782
 
783 783
         return $query;
784 784
     }
@@ -881,7 +881,7 @@  discard block
 block discarded – undo
881 881
             $str = (int)$str;
882 882
         }
883 883
 
884
-        return '\'' . $this->link->real_escape_string($str) . '\'';
884
+        return '\''.$this->link->real_escape_string($str).'\'';
885 885
     }
886 886
 
887 887
     /**
@@ -1034,18 +1034,18 @@  discard block
 block discarded – undo
1034 1034
      */
1035 1035
     protected function getSelectMmQueryParts($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '')
1036 1036
     {
1037
-        $foreign_table_as = $foreign_table == $local_table ? $foreign_table . StringUtility::getUniqueId('_join') : '';
1038
-        $mmWhere = $local_table ? $local_table . '.uid=' . $mm_table . '.uid_local' : '';
1037
+        $foreign_table_as = $foreign_table == $local_table ? $foreign_table.StringUtility::getUniqueId('_join') : '';
1038
+        $mmWhere = $local_table ? $local_table.'.uid='.$mm_table.'.uid_local' : '';
1039 1039
         $mmWhere .= ($local_table and $foreign_table) ? ' AND ' : '';
1040
-        $tables = ($local_table ? $local_table . ',' : '') . $mm_table;
1040
+        $tables = ($local_table ? $local_table.',' : '').$mm_table;
1041 1041
         if ($foreign_table) {
1042
-            $mmWhere .= ($foreign_table_as ?: $foreign_table) . '.uid=' . $mm_table . '.uid_foreign';
1043
-            $tables .= ',' . $foreign_table . ($foreign_table_as ? ' AS ' . $foreign_table_as : '');
1042
+            $mmWhere .= ($foreign_table_as ?: $foreign_table).'.uid='.$mm_table.'.uid_foreign';
1043
+            $tables .= ','.$foreign_table.($foreign_table_as ? ' AS '.$foreign_table_as : '');
1044 1044
         }
1045 1045
         return [
1046 1046
             'SELECT' => $select,
1047 1047
             'FROM' => $tables,
1048
-            'WHERE' => $mmWhere . ' ' . $whereClause,
1048
+            'WHERE' => $mmWhere.' '.$whereClause,
1049 1049
             'GROUPBY' => $groupBy,
1050 1050
             'ORDERBY' => $orderBy,
1051 1051
             'LIMIT' => $limit
@@ -1279,7 +1279,7 @@  discard block
 block discarded – undo
1279 1279
         }
1280 1280
 
1281 1281
         $host = $this->persistentDatabaseConnection
1282
-            ? 'p:' . $this->databaseHost
1282
+            ? 'p:'.$this->databaseHost
1283 1283
             : $this->databaseHost;
1284 1284
 
1285 1285
         // We are not using the TYPO3 CMS shim here as the database parameters in this class
@@ -1311,7 +1311,7 @@  discard block
 block discarded – undo
1311 1311
             foreach ($this->initializeCommandsAfterConnect as $command) {
1312 1312
                 if ($this->query($command) === false) {
1313 1313
                     GeneralUtility::sysLog(
1314
-                        'Could not initialize DB connection with query "' . $command . '": ' . $this->sql_error(),
1314
+                        'Could not initialize DB connection with query "'.$command.'": '.$this->sql_error(),
1315 1315
                         'core',
1316 1316
                         GeneralUtility::SYSLOG_SEVERITY_ERROR
1317 1317
                     );
@@ -1323,7 +1323,7 @@  discard block
 block discarded – undo
1323 1323
             $error_msg = $this->link->connect_error;
1324 1324
             $this->link = null;
1325 1325
             GeneralUtility::sysLog(
1326
-                'Could not connect to MySQL server ' . $host . ' with user ' . $this->databaseUsername . ': '
1326
+                'Could not connect to MySQL server '.$host.' with user '.$this->databaseUsername.': '
1327 1327
                 . $error_msg,
1328 1328
                 'core',
1329 1329
                 GeneralUtility::SYSLOG_SEVERITY_FATAL
@@ -1347,7 +1347,7 @@  discard block
 block discarded – undo
1347 1347
         $ret = $this->link->select_db($this->databaseName);
1348 1348
         if (!$ret) {
1349 1349
             GeneralUtility::sysLog(
1350
-                'Could not select MySQL database ' . $this->databaseName . ': ' . $this->sql_error(),
1350
+                'Could not select MySQL database '.$this->databaseName.': '.$this->sql_error(),
1351 1351
                 'core',
1352 1352
                 GeneralUtility::SYSLOG_SEVERITY_FATAL
1353 1353
             );
@@ -1377,7 +1377,7 @@  discard block
 block discarded – undo
1377 1377
         $db_list = $this->query('SELECT SCHEMA_NAME FROM information_schema.SCHEMATA');
1378 1378
         if ($db_list === false) {
1379 1379
             throw new \RuntimeException(
1380
-                'MySQL Error: Cannot get tablenames: "' . $this->sql_error() . '"!',
1380
+                'MySQL Error: Cannot get tablenames: "'.$this->sql_error().'"!',
1381 1381
                 1378457171
1382 1382
             );
1383 1383
         } else {
@@ -1408,7 +1408,7 @@  discard block
 block discarded – undo
1408 1408
     {
1409 1409
         $this->logDeprecation();
1410 1410
         $whichTables = [];
1411
-        $tables_result = $this->query('SHOW TABLE STATUS FROM `' . $this->databaseName . '`');
1411
+        $tables_result = $this->query('SHOW TABLE STATUS FROM `'.$this->databaseName.'`');
1412 1412
         if ($tables_result !== false) {
1413 1413
             while ($theTable = $tables_result->fetch_assoc()) {
1414 1414
                 $whichTables[$theTable['Name']] = $theTable;
@@ -1433,7 +1433,7 @@  discard block
 block discarded – undo
1433 1433
     {
1434 1434
         $this->logDeprecation();
1435 1435
         $output = [];
1436
-        $columns_res = $this->query('SHOW FULL COLUMNS FROM `' . $tableName . '`');
1436
+        $columns_res = $this->query('SHOW FULL COLUMNS FROM `'.$tableName.'`');
1437 1437
         if ($columns_res !== false) {
1438 1438
             while ($fieldRow = $columns_res->fetch_assoc()) {
1439 1439
                 $output[$fieldRow['Field']] = $fieldRow;
@@ -1454,7 +1454,7 @@  discard block
 block discarded – undo
1454 1454
     {
1455 1455
         $this->logDeprecation();
1456 1456
         $output = [];
1457
-        $keyRes = $this->query('SHOW KEYS FROM `' . $tableName . '`');
1457
+        $keyRes = $this->query('SHOW KEYS FROM `'.$tableName.'`');
1458 1458
         if ($keyRes !== false) {
1459 1459
             while ($keyRow = $keyRes->fetch_assoc()) {
1460 1460
                 $output[] = $keyRow;
@@ -1650,7 +1650,7 @@  discard block
 block discarded – undo
1650 1650
         if ($this->sql_pconnect()) {
1651 1651
             if (!$this->sql_select_db()) {
1652 1652
                 throw new \RuntimeException(
1653
-                    'TYPO3 Fatal Error: Cannot connect to the current database, "' . $this->databaseName . '"!',
1653
+                    'TYPO3 Fatal Error: Cannot connect to the current database, "'.$this->databaseName.'"!',
1654 1654
                     1270853883
1655 1655
                 );
1656 1656
             }
@@ -1721,7 +1721,7 @@  discard block
 block discarded – undo
1721 1721
 
1722 1722
         if ($sessionResult === false) {
1723 1723
             GeneralUtility::sysLog(
1724
-                'Error while retrieving the current charset session variables from the database: ' . $this->sql_error(),
1724
+                'Error while retrieving the current charset session variables from the database: '.$this->sql_error(),
1725 1725
                 'core',
1726 1726
                 GeneralUtility::SYSLOG_SEVERITY_ERROR
1727 1727
             );
@@ -1751,12 +1751,12 @@  discard block
 block discarded – undo
1751 1751
         foreach ($charsetRequiredVariables as $variableName) {
1752 1752
             if (empty($charsetVariables[$variableName])) {
1753 1753
                 GeneralUtility::sysLog(
1754
-                    'A required session variable is missing in the current MySQL connection: ' . $variableName,
1754
+                    'A required session variable is missing in the current MySQL connection: '.$variableName,
1755 1755
                     'core',
1756 1756
                     GeneralUtility::SYSLOG_SEVERITY_ERROR
1757 1757
                 );
1758 1758
                 throw new \RuntimeException(
1759
-                    'TYPO3 Fatal Error: Could not determine the value of the database session variable: ' . $variableName,
1759
+                    'TYPO3 Fatal Error: Could not determine the value of the database session variable: '.$variableName,
1760 1760
                     1381847779
1761 1761
                 );
1762 1762
             }
@@ -1769,9 +1769,9 @@  discard block
 block discarded – undo
1769 1769
 
1770 1770
         if (!$hasValidCharset) {
1771 1771
             throw new \RuntimeException(
1772
-                'It looks like the character set ' . $this->connectionCharset . ' is not used for this connection even though it is configured as connection charset. ' .
1773
-                'This TYPO3 installation is using the $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\'] property with the following value: "' .
1774
-                $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'] . '". Please make sure that this command does not overwrite the configured charset. ' .
1772
+                'It looks like the character set '.$this->connectionCharset.' is not used for this connection even though it is configured as connection charset. '.
1773
+                'This TYPO3 installation is using the $GLOBALS[\'TYPO3_CONF_VARS\'][\'SYS\'][\'setDBinit\'] property with the following value: "'.
1774
+                $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'].'". Please make sure that this command does not overwrite the configured charset. '.
1775 1775
                 'Please note that for the TYPO3 database everything other than utf8 is unsupported since version 4.7.',
1776 1776
                 1389697515
1777 1777
             );
@@ -1839,7 +1839,7 @@  discard block
 block discarded – undo
1839 1839
         if ($error || (int)$this->debugOutput === 2) {
1840 1840
             \TYPO3\CMS\Core\Utility\DebugUtility::debug(
1841 1841
                 [
1842
-                    'caller' => \Fab\Vidi\Database\DatabaseConnection::class . '::' . $func,
1842
+                    'caller' => \Fab\Vidi\Database\DatabaseConnection::class.'::'.$func,
1843 1843
                     'ERROR' => $error,
1844 1844
                     'lastBuiltQuery' => $query ? $query : $this->debug_lastBuiltQuery,
1845 1845
                     'debug_backtrace' => \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail()
@@ -1867,10 +1867,10 @@  discard block
 block discarded – undo
1867 1867
         $trace = debug_backtrace(0);
1868 1868
         array_shift($trace);
1869 1869
         $msg = 'Invalid database result detected: function TYPO3\\CMS\\Typo3DbLegacy\\Database\\DatabaseConnection->'
1870
-            . $trace[0]['function'] . ' called from file ' . substr($trace[0]['file'], (strlen(PATH_site) + 2))
1871
-            . ' in line ' . $trace[0]['line'] . '.';
1870
+            . $trace[0]['function'].' called from file '.substr($trace[0]['file'], (strlen(PATH_site) + 2))
1871
+            . ' in line '.$trace[0]['line'].'.';
1872 1872
         GeneralUtility::sysLog(
1873
-            $msg . ' Use a devLog extension to get more details.',
1873
+            $msg.' Use a devLog extension to get more details.',
1874 1874
             'core',
1875 1875
             GeneralUtility::SYSLOG_SEVERITY_ERROR
1876 1876
         );
@@ -1922,7 +1922,7 @@  discard block
 block discarded – undo
1922 1922
         $trail = \TYPO3\CMS\Core\Utility\DebugUtility::debugTrail();
1923 1923
         $explain_tables = [];
1924 1924
         $explain_output = [];
1925
-        $res = $this->sql_query('EXPLAIN ' . $query, $this->link);
1925
+        $res = $this->sql_query('EXPLAIN '.$query, $this->link);
1926 1926
         if (is_a($res, '\\mysqli_result')) {
1927 1927
             while ($tempRow = $this->sql_fetch_assoc($res)) {
1928 1928
                 $explain_output[] = $tempRow;
@@ -1936,10 +1936,10 @@  discard block
 block discarded – undo
1936 1936
             // Only enable output if it's really useful
1937 1937
             $debug = true;
1938 1938
             foreach ($explain_tables as $table) {
1939
-                $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
1939
+                $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \''.$table.'\'');
1940 1940
                 $isTable = $this->sql_num_rows($tableRes);
1941 1941
                 if ($isTable) {
1942
-                    $res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
1942
+                    $res = $this->sql_query('SHOW INDEX FROM '.$table, $this->link);
1943 1943
                     if (is_a($res, '\\mysqli_result')) {
1944 1944
                         while ($tempRow = $this->sql_fetch_assoc($res)) {
1945 1945
                             $indices_output[] = $tempRow;
@@ -1968,7 +1968,7 @@  discard block
 block discarded – undo
1968 1968
                     $data['indices'] = $indices_output;
1969 1969
                 }
1970 1970
                 if ($explainMode == 1) {
1971
-                    \TYPO3\CMS\Core\Utility\DebugUtility::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
1971
+                    \TYPO3\CMS\Core\Utility\DebugUtility::debug($data, 'Tables: '.$from_table, 'DB SQL EXPLAIN');
1972 1972
                 } elseif ($explainMode == 2) {
1973 1973
                     /** @var TimeTracker $timeTracker */
1974 1974
                     $timeTracker = GeneralUtility::makeInstance(TimeTracker::class);
Please login to merge, or discard this patch.
Classes/Service/FileReferenceService.php 2 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
     /**
70 70
      * Fetch the files given an object assuming
71 71
      *
72
-     * @param $propertyName
72
+     * @param string $propertyName
73 73
      * @param Content $object
74 74
      * @return File[]
75 75
      */
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
      * get the WHERE clause for the enabled fields of this TCA table
101 101
      * depending on the context
102 102
      *
103
-     * @param $tableName
103
+     * @param string $tableName
104 104
      * @return string
105 105
      */
106 106
     protected function getWhereClauseForEnabledFields($tableName)
Please login to merge, or discard this patch.
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -23,127 +23,127 @@
 block discarded – undo
23 23
 class FileReferenceService implements SingletonInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var array
28
-     */
29
-    static protected $instances = [];
30
-
31
-    /**
32
-     * Returns a class instance
33
-     *
34
-     * @return \Fab\Vidi\Service\FileReferenceService|object
35
-     */
36
-    static public function getInstance()
37
-    {
38
-        return GeneralUtility::makeInstance(\Fab\Vidi\Service\FileReferenceService::class);
39
-    }
40
-
41
-    /**
42
-     * @param Content $object
43
-     * @param string $propertyName
44
-     * @return File[]
45
-     */
46
-    public function findReferencedBy($propertyName, Content $object)
47
-    {
48
-
49
-        if (!isset(self::$instances[$object->getUid()][$propertyName])) {
50
-
51
-            // Initialize instances value
52
-            if (!isset(self::$instances[$object->getUid()])) {
53
-                self::$instances[$object->getUid()] = [];
54
-            }
55
-
56
-            $fieldName = GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName);
57
-            $field = Tca::table($object->getDataType())->field($fieldName);
58
-            if ($field->getForeignTable() === 'sys_file_reference') {
59
-                $files = $this->findByFileReference($propertyName, $object);
60
-                self::$instances[$object->getUid()][$propertyName] = $files;
61
-            } else {
62
-                // @todo the standard way of handling file references is by "sys_file_reference". Let see if there is other use cases...
63
-            }
64
-        }
65
-
66
-        return self::$instances[$object->getUid()][$propertyName];
67
-    }
68
-
69
-    /**
70
-     * Fetch the files given an object assuming
71
-     *
72
-     * @param $propertyName
73
-     * @param Content $object
74
-     * @return File[]
75
-     */
76
-    protected function findByFileReference($propertyName, Content $object)
77
-    {
78
-
79
-        $fileField = 'uid_local';
80
-        $tableName = 'sys_file_reference';
81
-
82
-        $clause = sprintf('tablenames = "%s" %s AND fieldname = "%s" AND uid_foreign = %s',
83
-            $object->getDataType(),
84
-            $this->getWhereClauseForEnabledFields($tableName),
85
-            GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName),
86
-            $object->getUid()
87
-        );
88
-        $rows = $this->getDatabaseConnection()->exec_SELECTgetRows($fileField, $tableName, $clause);
89
-
90
-        // Build array of Files
91
-        $files = [];
92
-        foreach ($rows as $row) {
93
-            $files[] = ResourceFactory::getInstance()->getFileObject($row[$fileField]);
94
-        }
95
-
96
-        return $files;
97
-    }
98
-
99
-    /**
100
-     * get the WHERE clause for the enabled fields of this TCA table
101
-     * depending on the context
102
-     *
103
-     * @param $tableName
104
-     * @return string
105
-     */
106
-    protected function getWhereClauseForEnabledFields($tableName)
107
-    {
108
-        if ($this->isFrontendMode()) {
109
-            // frontend context
110
-            $whereClause = $this->getPageRepository()->enableFields($tableName);
111
-            $whereClause .= $this->getPageRepository()->deleteClause($tableName);
112
-        } else {
113
-            // backend context
114
-            $whereClause = BackendUtility::BEenableFields($tableName);
115
-            $whereClause .= BackendUtility::deleteClause($tableName);
116
-        }
117
-        return $whereClause;
118
-    }
119
-
120
-    /**
121
-     * Returns whether the current mode is Frontend
122
-     *
123
-     * @return bool
124
-     */
125
-    protected function isFrontendMode()
126
-    {
127
-        return TYPO3_MODE === 'FE';
128
-    }
129
-
130
-    /**
131
-     * Returns an instance of the page repository.
132
-     *
133
-     * @return \TYPO3\CMS\Frontend\Page\PageRepository
134
-     */
135
-    protected function getPageRepository()
136
-    {
137
-        return $GLOBALS['TSFE']->sys_page;
138
-    }
139
-
140
-    /**
141
-     * Returns a pointer to the database.
142
-     *
143
-     * @return \Fab\Vidi\Database\DatabaseConnection
144
-     */
145
-    protected function getDatabaseConnection()
146
-    {
147
-        return $GLOBALS['TYPO3_DB'];
148
-    }
26
+	/**
27
+	 * @var array
28
+	 */
29
+	static protected $instances = [];
30
+
31
+	/**
32
+	 * Returns a class instance
33
+	 *
34
+	 * @return \Fab\Vidi\Service\FileReferenceService|object
35
+	 */
36
+	static public function getInstance()
37
+	{
38
+		return GeneralUtility::makeInstance(\Fab\Vidi\Service\FileReferenceService::class);
39
+	}
40
+
41
+	/**
42
+	 * @param Content $object
43
+	 * @param string $propertyName
44
+	 * @return File[]
45
+	 */
46
+	public function findReferencedBy($propertyName, Content $object)
47
+	{
48
+
49
+		if (!isset(self::$instances[$object->getUid()][$propertyName])) {
50
+
51
+			// Initialize instances value
52
+			if (!isset(self::$instances[$object->getUid()])) {
53
+				self::$instances[$object->getUid()] = [];
54
+			}
55
+
56
+			$fieldName = GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName);
57
+			$field = Tca::table($object->getDataType())->field($fieldName);
58
+			if ($field->getForeignTable() === 'sys_file_reference') {
59
+				$files = $this->findByFileReference($propertyName, $object);
60
+				self::$instances[$object->getUid()][$propertyName] = $files;
61
+			} else {
62
+				// @todo the standard way of handling file references is by "sys_file_reference". Let see if there is other use cases...
63
+			}
64
+		}
65
+
66
+		return self::$instances[$object->getUid()][$propertyName];
67
+	}
68
+
69
+	/**
70
+	 * Fetch the files given an object assuming
71
+	 *
72
+	 * @param $propertyName
73
+	 * @param Content $object
74
+	 * @return File[]
75
+	 */
76
+	protected function findByFileReference($propertyName, Content $object)
77
+	{
78
+
79
+		$fileField = 'uid_local';
80
+		$tableName = 'sys_file_reference';
81
+
82
+		$clause = sprintf('tablenames = "%s" %s AND fieldname = "%s" AND uid_foreign = %s',
83
+			$object->getDataType(),
84
+			$this->getWhereClauseForEnabledFields($tableName),
85
+			GeneralUtility::camelCaseToLowerCaseUnderscored($propertyName),
86
+			$object->getUid()
87
+		);
88
+		$rows = $this->getDatabaseConnection()->exec_SELECTgetRows($fileField, $tableName, $clause);
89
+
90
+		// Build array of Files
91
+		$files = [];
92
+		foreach ($rows as $row) {
93
+			$files[] = ResourceFactory::getInstance()->getFileObject($row[$fileField]);
94
+		}
95
+
96
+		return $files;
97
+	}
98
+
99
+	/**
100
+	 * get the WHERE clause for the enabled fields of this TCA table
101
+	 * depending on the context
102
+	 *
103
+	 * @param $tableName
104
+	 * @return string
105
+	 */
106
+	protected function getWhereClauseForEnabledFields($tableName)
107
+	{
108
+		if ($this->isFrontendMode()) {
109
+			// frontend context
110
+			$whereClause = $this->getPageRepository()->enableFields($tableName);
111
+			$whereClause .= $this->getPageRepository()->deleteClause($tableName);
112
+		} else {
113
+			// backend context
114
+			$whereClause = BackendUtility::BEenableFields($tableName);
115
+			$whereClause .= BackendUtility::deleteClause($tableName);
116
+		}
117
+		return $whereClause;
118
+	}
119
+
120
+	/**
121
+	 * Returns whether the current mode is Frontend
122
+	 *
123
+	 * @return bool
124
+	 */
125
+	protected function isFrontendMode()
126
+	{
127
+		return TYPO3_MODE === 'FE';
128
+	}
129
+
130
+	/**
131
+	 * Returns an instance of the page repository.
132
+	 *
133
+	 * @return \TYPO3\CMS\Frontend\Page\PageRepository
134
+	 */
135
+	protected function getPageRepository()
136
+	{
137
+		return $GLOBALS['TSFE']->sys_page;
138
+	}
139
+
140
+	/**
141
+	 * Returns a pointer to the database.
142
+	 *
143
+	 * @return \Fab\Vidi\Database\DatabaseConnection
144
+	 */
145
+	protected function getDatabaseConnection()
146
+	{
147
+		return $GLOBALS['TYPO3_DB'];
148
+	}
149 149
 }
Please login to merge, or discard this patch.
Classes/Utility/BackendUtility.php 3 patches
Unused Use Statements   -41 removed lines patch added patch discarded remove patch
@@ -8,50 +8,9 @@
 block discarded – undo
8 8
  * LICENSE.md file that was distributed with this source code.
9 9
  */
10 10
 
11
-use Psr\Log\LoggerInterface;
12
-use TYPO3\CMS\Backend\Backend\Shortcut\ShortcutRepository;
13 11
 use TYPO3\CMS\Backend\Routing\UriBuilder;
14
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
15
-use TYPO3\CMS\Core\Cache\CacheManager;
16
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
17
-use TYPO3\CMS\Core\Core\Environment;
18
-use TYPO3\CMS\Core\Database\Connection;
19 12
 use TYPO3\CMS\Core\Database\ConnectionPool;
20
-use TYPO3\CMS\Core\Database\Query\QueryBuilder;
21
-use TYPO3\CMS\Core\Database\Query\QueryHelper;
22
-use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
23
-use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
24
-use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
25
-use TYPO3\CMS\Core\Database\RelationHandler;
26
-use TYPO3\CMS\Core\Exception\SiteNotFoundException;
27
-use TYPO3\CMS\Core\Http\ServerRequest;
28
-use TYPO3\CMS\Core\Imaging\Icon;
29
-use TYPO3\CMS\Core\Imaging\IconFactory;
30
-use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
31
-use TYPO3\CMS\Core\Localization\LanguageService;
32
-use TYPO3\CMS\Core\Log\LogManager;
33
-use TYPO3\CMS\Core\Resource\AbstractFile;
34
-use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
35
-use TYPO3\CMS\Core\Resource\File;
36
-use TYPO3\CMS\Core\Resource\ProcessedFile;
37
-use TYPO3\CMS\Core\Resource\ResourceFactory;
38
-use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
39
-use TYPO3\CMS\Core\Routing\RouterInterface;
40
-use TYPO3\CMS\Core\Routing\SiteMatcher;
41
-use TYPO3\CMS\Core\Site\Entity\PseudoSite;
42
-use TYPO3\CMS\Core\Site\Entity\Site;
43
-use TYPO3\CMS\Core\Site\SiteFinder;
44
-use TYPO3\CMS\Core\Type\Bitmask\Permission;
45
-use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
46
-use TYPO3\CMS\Core\Utility\ArrayUtility;
47
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
48 13
 use TYPO3\CMS\Core\Utility\GeneralUtility;
49
-use TYPO3\CMS\Core\Utility\HttpUtility;
50
-use TYPO3\CMS\Core\Utility\MathUtility;
51
-use TYPO3\CMS\Core\Utility\PathUtility;
52
-use TYPO3\CMS\Core\Versioning\VersionState;
53
-use TYPO3\CMS\Frontend\Compatibility\LegacyDomainResolver;
54
-use TYPO3\CMS\Frontend\Page\PageRepository;
55 14
 
56 15
 /**
57 16
  * Standard functions available for the TYPO3 backend.
Please login to merge, or discard this patch.
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -61,115 +61,115 @@
 block discarded – undo
61 61
 class BackendUtility
62 62
 {
63 63
 
64
-    /*******************************************
64
+	/*******************************************
65 65
      *
66 66
      * SQL-related, selecting records, searching
67 67
      *
68 68
      *******************************************/
69
-    /**
70
-     * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field
71
-     * is configured in $GLOBALS['TCA'] for the tablename, $table
72
-     * This function should ALWAYS be called in the backend for selection on tables which
73
-     * are configured in $GLOBALS['TCA'] since it will ensure consistent selection of records,
74
-     * even if they are marked deleted (in which case the system must always treat them as non-existent!)
75
-     * In the frontend a function, ->enableFields(), is known to filter hidden-field, start- and endtime
76
-     * and fe_groups as well. But that is a job of the frontend, not the backend. If you need filtering
77
-     * on those fields as well in the backend you can use ->BEenableFields() though.
78
-     *
79
-     * @param string $table Table name present in $GLOBALS['TCA']
80
-     * @param string $tableAlias Table alias if any
81
-     * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0
82
-     */
83
-    public static function deleteClause($table, $tableAlias = '')
84
-    {
85
-        if (empty($GLOBALS['TCA'][$table]['ctrl']['delete'])) {
86
-            return '';
87
-        }
88
-        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
89
-            ->getQueryBuilderForTable($table)
90
-            ->expr();
91
-        return ' AND ' . $expressionBuilder->eq(
92
-                ($tableAlias ?: $table) . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
93
-                0
94
-            );
95
-    }
96
-    /**
97
-     * Backend implementation of enableFields()
98
-     * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime.
99
-     * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition.
100
-     * $GLOBALS["SIM_ACCESS_TIME"] is used for date.
101
-     *
102
-     * @param string $table The table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $GLOBALS['TCA'].
103
-     * @param bool $inv Means that the query will select all records NOT VISIBLE records (inverted selection)
104
-     * @return string WHERE clause part
105
-     */
106
-    public static function BEenableFields($table, $inv = false)
107
-    {
108
-        $ctrl = $GLOBALS['TCA'][$table]['ctrl'];
109
-        $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
110
-            ->getConnectionForTable($table)
111
-            ->getExpressionBuilder();
112
-        $query = $expressionBuilder->andX();
113
-        $invQuery = $expressionBuilder->orX();
69
+	/**
70
+	 * Returns the WHERE clause " AND NOT [tablename].[deleted-field]" if a deleted-field
71
+	 * is configured in $GLOBALS['TCA'] for the tablename, $table
72
+	 * This function should ALWAYS be called in the backend for selection on tables which
73
+	 * are configured in $GLOBALS['TCA'] since it will ensure consistent selection of records,
74
+	 * even if they are marked deleted (in which case the system must always treat them as non-existent!)
75
+	 * In the frontend a function, ->enableFields(), is known to filter hidden-field, start- and endtime
76
+	 * and fe_groups as well. But that is a job of the frontend, not the backend. If you need filtering
77
+	 * on those fields as well in the backend you can use ->BEenableFields() though.
78
+	 *
79
+	 * @param string $table Table name present in $GLOBALS['TCA']
80
+	 * @param string $tableAlias Table alias if any
81
+	 * @return string WHERE clause for filtering out deleted records, eg " AND tablename.deleted=0
82
+	 */
83
+	public static function deleteClause($table, $tableAlias = '')
84
+	{
85
+		if (empty($GLOBALS['TCA'][$table]['ctrl']['delete'])) {
86
+			return '';
87
+		}
88
+		$expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
89
+			->getQueryBuilderForTable($table)
90
+			->expr();
91
+		return ' AND ' . $expressionBuilder->eq(
92
+				($tableAlias ?: $table) . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
93
+				0
94
+			);
95
+	}
96
+	/**
97
+	 * Backend implementation of enableFields()
98
+	 * Notice that "fe_groups" is not selected for - only disabled, starttime and endtime.
99
+	 * Notice that deleted-fields are NOT filtered - you must ALSO call deleteClause in addition.
100
+	 * $GLOBALS["SIM_ACCESS_TIME"] is used for date.
101
+	 *
102
+	 * @param string $table The table from which to return enableFields WHERE clause. Table name must have a 'ctrl' section in $GLOBALS['TCA'].
103
+	 * @param bool $inv Means that the query will select all records NOT VISIBLE records (inverted selection)
104
+	 * @return string WHERE clause part
105
+	 */
106
+	public static function BEenableFields($table, $inv = false)
107
+	{
108
+		$ctrl = $GLOBALS['TCA'][$table]['ctrl'];
109
+		$expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
110
+			->getConnectionForTable($table)
111
+			->getExpressionBuilder();
112
+		$query = $expressionBuilder->andX();
113
+		$invQuery = $expressionBuilder->orX();
114 114
 
115
-        if (is_array($ctrl)) {
116
-            if (is_array($ctrl['enablecolumns'])) {
117
-                if ($ctrl['enablecolumns']['disabled'] ?? false) {
118
-                    $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
119
-                    $query->add($expressionBuilder->eq($field, 0));
120
-                    $invQuery->add($expressionBuilder->neq($field, 0));
121
-                }
122
-                if ($ctrl['enablecolumns']['starttime'] ?? false) {
123
-                    $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
124
-                    $query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
125
-                    $invQuery->add(
126
-                        $expressionBuilder->andX(
127
-                            $expressionBuilder->neq($field, 0),
128
-                            $expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
129
-                        )
130
-                    );
131
-                }
132
-                if ($ctrl['enablecolumns']['endtime'] ?? false) {
133
-                    $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
134
-                    $query->add(
135
-                        $expressionBuilder->orX(
136
-                            $expressionBuilder->eq($field, 0),
137
-                            $expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
138
-                        )
139
-                    );
140
-                    $invQuery->add(
141
-                        $expressionBuilder->andX(
142
-                            $expressionBuilder->neq($field, 0),
143
-                            $expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
144
-                        )
145
-                    );
146
-                }
147
-            }
148
-        }
115
+		if (is_array($ctrl)) {
116
+			if (is_array($ctrl['enablecolumns'])) {
117
+				if ($ctrl['enablecolumns']['disabled'] ?? false) {
118
+					$field = $table . '.' . $ctrl['enablecolumns']['disabled'];
119
+					$query->add($expressionBuilder->eq($field, 0));
120
+					$invQuery->add($expressionBuilder->neq($field, 0));
121
+				}
122
+				if ($ctrl['enablecolumns']['starttime'] ?? false) {
123
+					$field = $table . '.' . $ctrl['enablecolumns']['starttime'];
124
+					$query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
125
+					$invQuery->add(
126
+						$expressionBuilder->andX(
127
+							$expressionBuilder->neq($field, 0),
128
+							$expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
129
+						)
130
+					);
131
+				}
132
+				if ($ctrl['enablecolumns']['endtime'] ?? false) {
133
+					$field = $table . '.' . $ctrl['enablecolumns']['endtime'];
134
+					$query->add(
135
+						$expressionBuilder->orX(
136
+							$expressionBuilder->eq($field, 0),
137
+							$expressionBuilder->gt($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
138
+						)
139
+					);
140
+					$invQuery->add(
141
+						$expressionBuilder->andX(
142
+							$expressionBuilder->neq($field, 0),
143
+							$expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME'])
144
+						)
145
+					);
146
+				}
147
+			}
148
+		}
149 149
 
150
-        if ($query->count() === 0) {
151
-            return '';
152
-        }
150
+		if ($query->count() === 0) {
151
+			return '';
152
+		}
153 153
 
154
-        return ' AND ' . ($inv ? $invQuery : $query);
155
-    }
154
+		return ' AND ' . ($inv ? $invQuery : $query);
155
+	}
156 156
 
157
-    /**
158
-     * Returns the URL to a given module
159
-     *
160
-     * @param string $moduleName Name of the module
161
-     * @param array $urlParameters URL parameters that should be added as key value pairs
162
-     * @return string Calculated URL
163
-     */
164
-    public static function getModuleUrl($moduleName, $urlParameters = [])
165
-    {
166
-        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
167
-        try {
168
-            $uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters);
169
-        } catch (\TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) {
170
-            $uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters);
171
-        }
172
-        return (string)$uri;
173
-    }
157
+	/**
158
+	 * Returns the URL to a given module
159
+	 *
160
+	 * @param string $moduleName Name of the module
161
+	 * @param array $urlParameters URL parameters that should be added as key value pairs
162
+	 * @return string Calculated URL
163
+	 */
164
+	public static function getModuleUrl($moduleName, $urlParameters = [])
165
+	{
166
+		$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
167
+		try {
168
+			$uri = $uriBuilder->buildUriFromRoute($moduleName, $urlParameters);
169
+		} catch (\TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException $e) {
170
+			$uri = $uriBuilder->buildUriFromRoutePath($moduleName, $urlParameters);
171
+		}
172
+		return (string)$uri;
173
+	}
174 174
 
175 175
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -88,8 +88,8 @@  discard block
 block discarded – undo
88 88
         $expressionBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
89 89
             ->getQueryBuilderForTable($table)
90 90
             ->expr();
91
-        return ' AND ' . $expressionBuilder->eq(
92
-                ($tableAlias ?: $table) . '.' . $GLOBALS['TCA'][$table]['ctrl']['delete'],
91
+        return ' AND '.$expressionBuilder->eq(
92
+                ($tableAlias ?: $table).'.'.$GLOBALS['TCA'][$table]['ctrl']['delete'],
93 93
                 0
94 94
             );
95 95
     }
@@ -115,12 +115,12 @@  discard block
 block discarded – undo
115 115
         if (is_array($ctrl)) {
116 116
             if (is_array($ctrl['enablecolumns'])) {
117 117
                 if ($ctrl['enablecolumns']['disabled'] ?? false) {
118
-                    $field = $table . '.' . $ctrl['enablecolumns']['disabled'];
118
+                    $field = $table.'.'.$ctrl['enablecolumns']['disabled'];
119 119
                     $query->add($expressionBuilder->eq($field, 0));
120 120
                     $invQuery->add($expressionBuilder->neq($field, 0));
121 121
                 }
122 122
                 if ($ctrl['enablecolumns']['starttime'] ?? false) {
123
-                    $field = $table . '.' . $ctrl['enablecolumns']['starttime'];
123
+                    $field = $table.'.'.$ctrl['enablecolumns']['starttime'];
124 124
                     $query->add($expressionBuilder->lte($field, (int)$GLOBALS['SIM_ACCESS_TIME']));
125 125
                     $invQuery->add(
126 126
                         $expressionBuilder->andX(
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
                     );
131 131
                 }
132 132
                 if ($ctrl['enablecolumns']['endtime'] ?? false) {
133
-                    $field = $table . '.' . $ctrl['enablecolumns']['endtime'];
133
+                    $field = $table.'.'.$ctrl['enablecolumns']['endtime'];
134 134
                     $query->add(
135 135
                         $expressionBuilder->orX(
136 136
                             $expressionBuilder->eq($field, 0),
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
             return '';
152 152
         }
153 153
 
154
-        return ' AND ' . ($inv ? $invQuery : $query);
154
+        return ' AND '.($inv ? $invQuery : $query);
155 155
     }
156 156
 
157 157
     /**
Please login to merge, or discard this patch.
ext_tables.php 2 patches
Indentation   +171 added lines, -171 removed lines patch added patch discarded remove patch
@@ -3,175 +3,175 @@
 block discarded – undo
3 3
 
4 4
 call_user_func(function () {
5 5
 
6
-    // Check from Vidi configuration what default module should be loaded.
7
-    // Make sure the class exists to avoid a Runtime Error
8
-    if (TYPO3_MODE === 'BE') {
9
-
10
-        // Add content main module before 'user'
11
-        if (!isset($GLOBALS['TBE_MODULES']['content'])) {
12
-
13
-            // Position module "content" after module "user" manually. No API is available for that, it seems...
14
-            $modules = [];
15
-            foreach ($GLOBALS['TBE_MODULES'] as $key => $val) {
16
-                if ($key === 'user') {
17
-                    $modules['content'] = '';
18
-                }
19
-                $modules[$key] = $val;
20
-            }
21
-            $GLOBALS['TBE_MODULES'] = $modules;
22
-
23
-            // Register "data management" module.
24
-            \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule(
25
-                'content',
26
-                '',
27
-                '',
28
-                '',
29
-                [
30
-                    'name' => 'content',
31
-                    'access' => 'user,group',
32
-                    'labels' => [
33
-                        'll_ref' => 'LLL:EXT:vidi/Resources/Private/Language/content_module.xlf',
34
-                    ],
35
-                ]
36
-            );
37
-        }
38
-
39
-        $configuration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
40
-            \TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class
41
-        )->get('vidi');
42
-
43
-        $pids = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configuration['default_pid'], true);
44
-        $defaultPid = array_shift($pids);
45
-        $defaultPids = [];
46
-        foreach ($pids as $dataTypeAndPid) {
47
-            $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(':', $dataTypeAndPid);
48
-            if (count($parts) === 2) {
49
-                $defaultPids[$parts[0]] = $parts[1];
50
-            }
51
-        }
52
-
53
-        // Loop around the data types and register them to be displayed within a BE module.
54
-        if ($configuration['data_types']) {
55
-
56
-            $dataTypes = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configuration['data_types'], true);
57
-            foreach ($dataTypes as $dataType) {
58
-
59
-
60
-                /** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
61
-                $moduleLoader = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class, $dataType);
62
-
63
-                // Special case already defined in Vidi.
64
-                if ($dataType === 'fe_users') {
65
-                    $languageFile = 'LLL:EXT:vidi/Resources/Private/Language/fe_users.xlf';
66
-                    $icon = 'EXT:core/Resources/Public/Icons/T3Icons/status/status-user-frontend.svg';
67
-                    $icon = 'EXT:vidi/Resources/Public/Images/fe_users.svg';
68
-                } elseif ($dataType === 'fe_groups') {
69
-                    $languageFile = 'LLL:EXT:vidi/Resources/Private/Language/fe_groups.xlf';
70
-                    $icon = 'EXT:core/Resources/Public/Icons/T3Icons/status/status-user-group-frontend.svg';
71
-                    $icon = 'EXT:vidi/Resources/Public/Images/fe_groups.svg';
72
-                } else {
73
-                    /** @var \Fab\Vidi\Backend\LanguageFileGenerator $languageService */
74
-                    $languageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Fab\Vidi\Backend\LanguageFileGenerator::class);
75
-                    $languageFile = $languageService->generate($dataType);
76
-                    $icon = '';
77
-                }
78
-
79
-                $pid = isset($defaultPids[$dataType]) ? $defaultPids[$dataType] : $defaultPid;
80
-
81
-                /** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
82
-                $moduleLoader->setIcon($icon)
83
-                    ->setModuleLanguageFile($languageFile)
84
-                    ->setDefaultPid($pid)
85
-                    ->register();
86
-            }
87
-        }
88
-
89
-        // Possible Static TS loading
90
-        if (true === isset($configuration['autoload_typoscript']) && false === (bool)$configuration['autoload_typoscript']) {
91
-            \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('vidi', 'Configuration/TypoScript', 'Vidi: versatile and interactive display');
92
-        }
93
-
94
-        // Register List2 only if beta feature is enabled.
95
-        // @todo let see what we do with that
96
-        #if ($configuration['activate_beta_features']) {
97
-        #	$labelFile = 'LLL:EXT:vidi/Resources/Private/Language/locallang_module.xlf';
98
-        #
99
-        #	if (!$configuration['hide_module_list']) {
100
-        #		$labelFile = 'LLL:EXT:vidi/Resources/Private/Language/locallang_module_transitional.xlf';
101
-        #	}
102
-        #
103
-        #	\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
104
-        #		'vidi',
105
-        #		'web', // Make module a submodule of 'web'
106
-        #		'm1', // Submodule key
107
-        #		'after:list', // Position
108
-        #		array(
109
-        #			'Content' => 'index, list, delete, update, edit, copy, move, localize, sort, copyClipboard, moveClipboard',
110
-        #			'Tool' => 'welcome, work',
111
-        #			'Facet' => 'autoSuggest, autoSuggests',
112
-        #			'Selection' => 'edit, update, create, delete, list, show',
113
-        #			'UserPreferences' => 'save',
114
-        #			'Clipboard' => 'save, flush, show',
115
-        #		), array(
116
-        #			'access' => 'user,group',
117
-        #			'icon' => 'EXT:vidi/Resources/Public/Images/list.png',
118
-        #			'labels' => $labelFile,
119
-        #		)
120
-        #	);
121
-        #}
122
-        #if ($configuration['hide_module_list']) {
123
-        #
124
-        #	// Default User TSConfig to be added in any case.
125
-        #	TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig('
126
-        #
127
-        #		# Hide the module in the BE.
128
-        #		options.hideModules.web := addToList(list)
129
-        #	');
130
-        #}
131
-
132
-        /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager */
133
-        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
134
-
135
-        /** @var $signalSlotDispatcher \TYPO3\CMS\Extbase\SignalSlot\Dispatcher */
136
-        $signalSlotDispatcher = $objectManager->get('TYPO3\CMS\Extbase\SignalSlot\Dispatcher');
137
-
138
-        // Connect "processContentData" signal slot with the "ContentObjectProcessor".
139
-        $signalSlotDispatcher->connect(
140
-            'Fab\Vidi\Controller\Backend\ContentController',
141
-            'processContentData',
142
-            'Fab\Vidi\Processor\ContentObjectProcessor',
143
-            'processRelations',
144
-            true
145
-        );
146
-
147
-        // Connect "processContentData" signal with the "MarkerProcessor".
148
-        $signalSlotDispatcher->connect(
149
-            'Fab\Vidi\Controller\Backend\ContentController',
150
-            'processContentData',
151
-            'Fab\Vidi\Processor\MarkerProcessor',
152
-            'processMarkers',
153
-            true
154
-        );
155
-
156
-        // Register default Tools for Vidi.
157
-        \Fab\Vidi\Tool\ToolRegistry::getInstance()->register('*', 'Fab\Vidi\Tool\ModulePreferencesTool');
158
-        \Fab\Vidi\Tool\ToolRegistry::getInstance()->register('*', 'Fab\Vidi\Tool\RelationAnalyserTool');
159
-    }
160
-
161
-    // Add new sprite icon.
162
-    $icons = [
163
-        'go' => 'EXT:vidi/Resources/Public/Images/bullet_go.png',
164
-        'query' => 'EXT:vidi/Resources/Public/Images/drive_disk.png',
165
-    ];
166
-    /** @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */
167
-    $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
168
-    foreach ($icons as $key => $icon) {
169
-        $iconRegistry->registerIcon('extensions-vidi-' . $key,
170
-            \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
171
-            [
172
-                'source' => $icon
173
-            ]
174
-        );
175
-    }
176
-    unset($iconRegistry);
6
+	// Check from Vidi configuration what default module should be loaded.
7
+	// Make sure the class exists to avoid a Runtime Error
8
+	if (TYPO3_MODE === 'BE') {
9
+
10
+		// Add content main module before 'user'
11
+		if (!isset($GLOBALS['TBE_MODULES']['content'])) {
12
+
13
+			// Position module "content" after module "user" manually. No API is available for that, it seems...
14
+			$modules = [];
15
+			foreach ($GLOBALS['TBE_MODULES'] as $key => $val) {
16
+				if ($key === 'user') {
17
+					$modules['content'] = '';
18
+				}
19
+				$modules[$key] = $val;
20
+			}
21
+			$GLOBALS['TBE_MODULES'] = $modules;
22
+
23
+			// Register "data management" module.
24
+			\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule(
25
+				'content',
26
+				'',
27
+				'',
28
+				'',
29
+				[
30
+					'name' => 'content',
31
+					'access' => 'user,group',
32
+					'labels' => [
33
+						'll_ref' => 'LLL:EXT:vidi/Resources/Private/Language/content_module.xlf',
34
+					],
35
+				]
36
+			);
37
+		}
38
+
39
+		$configuration = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
40
+			\TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class
41
+		)->get('vidi');
42
+
43
+		$pids = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configuration['default_pid'], true);
44
+		$defaultPid = array_shift($pids);
45
+		$defaultPids = [];
46
+		foreach ($pids as $dataTypeAndPid) {
47
+			$parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(':', $dataTypeAndPid);
48
+			if (count($parts) === 2) {
49
+				$defaultPids[$parts[0]] = $parts[1];
50
+			}
51
+		}
52
+
53
+		// Loop around the data types and register them to be displayed within a BE module.
54
+		if ($configuration['data_types']) {
55
+
56
+			$dataTypes = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configuration['data_types'], true);
57
+			foreach ($dataTypes as $dataType) {
58
+
59
+
60
+				/** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
61
+				$moduleLoader = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class, $dataType);
62
+
63
+				// Special case already defined in Vidi.
64
+				if ($dataType === 'fe_users') {
65
+					$languageFile = 'LLL:EXT:vidi/Resources/Private/Language/fe_users.xlf';
66
+					$icon = 'EXT:core/Resources/Public/Icons/T3Icons/status/status-user-frontend.svg';
67
+					$icon = 'EXT:vidi/Resources/Public/Images/fe_users.svg';
68
+				} elseif ($dataType === 'fe_groups') {
69
+					$languageFile = 'LLL:EXT:vidi/Resources/Private/Language/fe_groups.xlf';
70
+					$icon = 'EXT:core/Resources/Public/Icons/T3Icons/status/status-user-group-frontend.svg';
71
+					$icon = 'EXT:vidi/Resources/Public/Images/fe_groups.svg';
72
+				} else {
73
+					/** @var \Fab\Vidi\Backend\LanguageFileGenerator $languageService */
74
+					$languageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(Fab\Vidi\Backend\LanguageFileGenerator::class);
75
+					$languageFile = $languageService->generate($dataType);
76
+					$icon = '';
77
+				}
78
+
79
+				$pid = isset($defaultPids[$dataType]) ? $defaultPids[$dataType] : $defaultPid;
80
+
81
+				/** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
82
+				$moduleLoader->setIcon($icon)
83
+					->setModuleLanguageFile($languageFile)
84
+					->setDefaultPid($pid)
85
+					->register();
86
+			}
87
+		}
88
+
89
+		// Possible Static TS loading
90
+		if (true === isset($configuration['autoload_typoscript']) && false === (bool)$configuration['autoload_typoscript']) {
91
+			\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('vidi', 'Configuration/TypoScript', 'Vidi: versatile and interactive display');
92
+		}
93
+
94
+		// Register List2 only if beta feature is enabled.
95
+		// @todo let see what we do with that
96
+		#if ($configuration['activate_beta_features']) {
97
+		#	$labelFile = 'LLL:EXT:vidi/Resources/Private/Language/locallang_module.xlf';
98
+		#
99
+		#	if (!$configuration['hide_module_list']) {
100
+		#		$labelFile = 'LLL:EXT:vidi/Resources/Private/Language/locallang_module_transitional.xlf';
101
+		#	}
102
+		#
103
+		#	\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
104
+		#		'vidi',
105
+		#		'web', // Make module a submodule of 'web'
106
+		#		'm1', // Submodule key
107
+		#		'after:list', // Position
108
+		#		array(
109
+		#			'Content' => 'index, list, delete, update, edit, copy, move, localize, sort, copyClipboard, moveClipboard',
110
+		#			'Tool' => 'welcome, work',
111
+		#			'Facet' => 'autoSuggest, autoSuggests',
112
+		#			'Selection' => 'edit, update, create, delete, list, show',
113
+		#			'UserPreferences' => 'save',
114
+		#			'Clipboard' => 'save, flush, show',
115
+		#		), array(
116
+		#			'access' => 'user,group',
117
+		#			'icon' => 'EXT:vidi/Resources/Public/Images/list.png',
118
+		#			'labels' => $labelFile,
119
+		#		)
120
+		#	);
121
+		#}
122
+		#if ($configuration['hide_module_list']) {
123
+		#
124
+		#	// Default User TSConfig to be added in any case.
125
+		#	TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig('
126
+		#
127
+		#		# Hide the module in the BE.
128
+		#		options.hideModules.web := addToList(list)
129
+		#	');
130
+		#}
131
+
132
+		/** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager */
133
+		$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
134
+
135
+		/** @var $signalSlotDispatcher \TYPO3\CMS\Extbase\SignalSlot\Dispatcher */
136
+		$signalSlotDispatcher = $objectManager->get('TYPO3\CMS\Extbase\SignalSlot\Dispatcher');
137
+
138
+		// Connect "processContentData" signal slot with the "ContentObjectProcessor".
139
+		$signalSlotDispatcher->connect(
140
+			'Fab\Vidi\Controller\Backend\ContentController',
141
+			'processContentData',
142
+			'Fab\Vidi\Processor\ContentObjectProcessor',
143
+			'processRelations',
144
+			true
145
+		);
146
+
147
+		// Connect "processContentData" signal with the "MarkerProcessor".
148
+		$signalSlotDispatcher->connect(
149
+			'Fab\Vidi\Controller\Backend\ContentController',
150
+			'processContentData',
151
+			'Fab\Vidi\Processor\MarkerProcessor',
152
+			'processMarkers',
153
+			true
154
+		);
155
+
156
+		// Register default Tools for Vidi.
157
+		\Fab\Vidi\Tool\ToolRegistry::getInstance()->register('*', 'Fab\Vidi\Tool\ModulePreferencesTool');
158
+		\Fab\Vidi\Tool\ToolRegistry::getInstance()->register('*', 'Fab\Vidi\Tool\RelationAnalyserTool');
159
+	}
160
+
161
+	// Add new sprite icon.
162
+	$icons = [
163
+		'go' => 'EXT:vidi/Resources/Public/Images/bullet_go.png',
164
+		'query' => 'EXT:vidi/Resources/Public/Images/drive_disk.png',
165
+	];
166
+	/** @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */
167
+	$iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
168
+	foreach ($icons as $key => $icon) {
169
+		$iconRegistry->registerIcon('extensions-vidi-' . $key,
170
+			\TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
171
+			[
172
+				'source' => $icon
173
+			]
174
+		);
175
+	}
176
+	unset($iconRegistry);
177 177
 });
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 defined('TYPO3_MODE') or die();
3 3
 
4
-call_user_func(function () {
4
+call_user_func(function() {
5 5
 
6 6
     // Check from Vidi configuration what default module should be loaded.
7 7
     // Make sure the class exists to avoid a Runtime Error
@@ -166,7 +166,7 @@  discard block
 block discarded – undo
166 166
     /** @var \TYPO3\CMS\Core\Imaging\IconRegistry $iconRegistry */
167 167
     $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
168 168
     foreach ($icons as $key => $icon) {
169
-        $iconRegistry->registerIcon('extensions-vidi-' . $key,
169
+        $iconRegistry->registerIcon('extensions-vidi-'.$key,
170 170
             \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
171 171
             [
172 172
                 'source' => $icon
Please login to merge, or discard this patch.
Tests/Unit/Tca/GridServiceTest.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@
 block discarded – undo
51 51
 	#public function getLabelReturnNameAsValue() {
52 52
 	#	$GLOBALS['LANG'] = $this->getMock('TYPO3\CMS\Lang\LanguageService', [], [], '', false);
53 53
 	#	$GLOBALS['LANG']->expects($this->once())->method('sL')->will($this->returnValue('Name'));
54
-    #
54
+	#
55 55
 	#	$this->assertEquals('Name', $this->fixture->getLabel('name'));
56 56
 	#}
57 57
 
Please login to merge, or discard this patch.
Classes/Domain/Validator/LanguageValidator.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -16,27 +16,27 @@
 block discarded – undo
16 16
 class LanguageValidator
17 17
 {
18 18
 
19
-    /**
20
-     * Check whether the $language is valid.
21
-     *
22
-     * @param int $language
23
-     * @throws \Exception
24
-     * @return void
25
-     */
26
-    public function validate($language)
27
-    {
19
+	/**
20
+	 * Check whether the $language is valid.
21
+	 *
22
+	 * @param int $language
23
+	 * @throws \Exception
24
+	 * @return void
25
+	 */
26
+	public function validate($language)
27
+	{
28 28
 
29
-        if (!$this->getLanguageService()->languageExists((int)$language)) {
30
-            throw new \Exception('The language "' . $language . '" does not exist', 1351605542);
31
-        }
32
-    }
29
+		if (!$this->getLanguageService()->languageExists((int)$language)) {
30
+			throw new \Exception('The language "' . $language . '" does not exist', 1351605542);
31
+		}
32
+	}
33 33
 
34
-    /**
35
-     * @return \Fab\Vidi\Language\LanguageService|object
36
-     */
37
-    protected function getLanguageService()
38
-    {
39
-        return GeneralUtility::makeInstance(\Fab\Vidi\Language\LanguageService::class);
40
-    }
34
+	/**
35
+	 * @return \Fab\Vidi\Language\LanguageService|object
36
+	 */
37
+	protected function getLanguageService()
38
+	{
39
+		return GeneralUtility::makeInstance(\Fab\Vidi\Language\LanguageService::class);
40
+	}
41 41
 
42 42
 }
Please login to merge, or discard this patch.
Classes/Domain/Validator/ToolValidator.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -18,36 +18,36 @@
 block discarded – undo
18 18
 class ToolValidator extends AbstractValidator
19 19
 {
20 20
 
21
-    /**
22
-     * Check whether $tool is valid.
23
-     *
24
-     * @param string $tool
25
-     * @return void
26
-     */
27
-    public function isValid($tool)
28
-    {
29
-
30
-        $dataType = $this->getModuleLoader()->getDataType();
31
-        $isValid = ToolRegistry::getInstance()->isAllowed($dataType, $tool);
32
-
33
-        if (!$isValid) {
34
-            $message = sprintf('This Tool "%s" is not allowed for the current data type.', $tool);
35
-            $this->addError($message, 1409041510);
36
-        }
37
-
38
-        if (!class_exists($tool)) {
39
-            $message = sprintf('I could not find class "%s"', $tool);
40
-            $this->addError($message, 1409041511);
41
-        }
42
-    }
43
-
44
-    /**
45
-     * Get the Vidi Module Loader.
46
-     *
47
-     * @return \Fab\Vidi\Module\ModuleLoader|object
48
-     */
49
-    protected function getModuleLoader()
50
-    {
51
-        return GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class);
52
-    }
21
+	/**
22
+	 * Check whether $tool is valid.
23
+	 *
24
+	 * @param string $tool
25
+	 * @return void
26
+	 */
27
+	public function isValid($tool)
28
+	{
29
+
30
+		$dataType = $this->getModuleLoader()->getDataType();
31
+		$isValid = ToolRegistry::getInstance()->isAllowed($dataType, $tool);
32
+
33
+		if (!$isValid) {
34
+			$message = sprintf('This Tool "%s" is not allowed for the current data type.', $tool);
35
+			$this->addError($message, 1409041510);
36
+		}
37
+
38
+		if (!class_exists($tool)) {
39
+			$message = sprintf('I could not find class "%s"', $tool);
40
+			$this->addError($message, 1409041511);
41
+		}
42
+	}
43
+
44
+	/**
45
+	 * Get the Vidi Module Loader.
46
+	 *
47
+	 * @return \Fab\Vidi\Module\ModuleLoader|object
48
+	 */
49
+	protected function getModuleLoader()
50
+	{
51
+		return GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class);
52
+	}
53 53
 }
Please login to merge, or discard this patch.
Classes/Domain/Repository/ContentRepositoryFactory.php 1 patch
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -17,44 +17,44 @@
 block discarded – undo
17 17
 class ContentRepositoryFactory implements SingletonInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var array
22
-     */
23
-    static protected $instances = [];
24
-
25
-    /**
26
-     * Returns a class instance of a repository.
27
-     * If not data type is given, get the value from the module loader.
28
-     *
29
-     * @param string $dataType
30
-     * @param string $sourceFieldName
31
-     * @return \Fab\Vidi\Domain\Repository\ContentRepository
32
-     */
33
-    static public function getInstance($dataType = null, $sourceFieldName = '')
34
-    {
35
-
36
-        /** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
37
-        if (is_null($dataType)) {
38
-
39
-            // Try to get the data type from the module loader.
40
-            $moduleLoader = GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class);
41
-            $dataType = $moduleLoader->getDataType();
42
-        }
43
-
44
-        // This should not happen.
45
-        if (!$dataType) {
46
-            throw new \RuntimeException('No data type given nor could be fetched by the module loader.', 1376118278);
47
-        }
48
-
49
-        if (empty(self::$instances[$dataType])) {
50
-            $className = 'Fab\Vidi\Domain\Repository\ContentRepository';
51
-            self::$instances[$dataType] = GeneralUtility::makeInstance($className, $dataType, $sourceFieldName);
52
-        }
53
-
54
-        /** @var ContentRepository $contentRepository */
55
-        $contentRepository = self::$instances[$dataType];
56
-        $contentRepository->setSourceFieldName($sourceFieldName);
57
-        return $contentRepository;
58
-    }
20
+	/**
21
+	 * @var array
22
+	 */
23
+	static protected $instances = [];
24
+
25
+	/**
26
+	 * Returns a class instance of a repository.
27
+	 * If not data type is given, get the value from the module loader.
28
+	 *
29
+	 * @param string $dataType
30
+	 * @param string $sourceFieldName
31
+	 * @return \Fab\Vidi\Domain\Repository\ContentRepository
32
+	 */
33
+	static public function getInstance($dataType = null, $sourceFieldName = '')
34
+	{
35
+
36
+		/** @var \Fab\Vidi\Module\ModuleLoader $moduleLoader */
37
+		if (is_null($dataType)) {
38
+
39
+			// Try to get the data type from the module loader.
40
+			$moduleLoader = GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class);
41
+			$dataType = $moduleLoader->getDataType();
42
+		}
43
+
44
+		// This should not happen.
45
+		if (!$dataType) {
46
+			throw new \RuntimeException('No data type given nor could be fetched by the module loader.', 1376118278);
47
+		}
48
+
49
+		if (empty(self::$instances[$dataType])) {
50
+			$className = 'Fab\Vidi\Domain\Repository\ContentRepository';
51
+			self::$instances[$dataType] = GeneralUtility::makeInstance($className, $dataType, $sourceFieldName);
52
+		}
53
+
54
+		/** @var ContentRepository $contentRepository */
55
+		$contentRepository = self::$instances[$dataType];
56
+		$contentRepository->setSourceFieldName($sourceFieldName);
57
+		return $contentRepository;
58
+	}
59 59
 
60 60
 }
Please login to merge, or discard this patch.