Completed
Push — master ( 6c8968...c3386c )
by Tim
20s
created

AbstractSubject::hasHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Subjects\AbstractSubject
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Subjects;
22
23
use Psr\Log\LoggerInterface;
24
use League\Flysystem\Filesystem;
25
use League\Flysystem\Adapter\Local;
26
use League\Flysystem\FilesystemInterface;
27
use Goodby\CSV\Import\Standard\Lexer;
28
use Goodby\CSV\Import\Standard\LexerConfig;
29
use Goodby\CSV\Import\Standard\Interpreter;
30
use TechDivision\Import\Utils\RegistryKeys;
31
use TechDivision\Import\Utils\ConfigurationKeys;
32
use TechDivision\Import\Services\RegistryProcessor;
33
use TechDivision\Import\Callbacks\CallbackInterface;
34
use TechDivision\Import\Observers\ObserverInterface;
35
use TechDivision\Import\Services\RegistryProcessorInterface;
36
use TechDivision\Import\Configuration\SubjectInterface as SubjectConfigurationInterface;
37
38
/**
39
 * An abstract subject implementation.
40
 *
41
 * @author    Tim Wagner <[email protected]>
42
 * @copyright 2016 TechDivision GmbH <[email protected]>
43
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
44
 * @link      https://github.com/techdivision/import
45
 * @link      http://www.techdivision.com
46
 */
47
abstract class AbstractSubject implements SubjectInterface
48
{
49
50
    /**
51
     * The root directory for the virtual filesystem.
52
     *
53
     * @var string
54
     */
55
    protected $rootDir;
56
57
    /**
58
     * The system configuration.
59
     *
60
     * @var \TechDivision\Import\Configuration\SubjectInterface
61
     */
62
    protected $configuration;
63
64
    /**
65
     * The system logger implementation.
66
     *
67
     * @var \Psr\Log\LoggerInterface
68
     */
69
    protected $systemLogger;
70
71
    /**
72
     * The RegistryProcessor instance to handle running threads.
73
     *
74
     * @var \TechDivision\Import\Services\RegistryProcessorInterface
75
     */
76
    protected $registryProcessor;
77
78
    /**
79
     * The actions unique serial.
80
     *
81
     * @var string
82
     */
83
    protected $serial;
84
85
    /**
86
     * The name of the file to be imported.
87
     *
88
     * @var string
89
     */
90
    protected $filename;
91
92
    /**
93
     * Array with the subject's observers.
94
     *
95
     * @var array
96
     */
97
    protected $observers = array();
98
99
    /**
100
     * Array with the subject's callbacks.
101
     *
102
     * @var array
103
     */
104
    protected $callbacks = array();
105
106
    /**
107
     * Contain's the column names from the header line.
108
     *
109
     * @var array
110
     */
111
    protected $headers = array();
112
113
    /**
114
     * The virtual filesystem instance.
115
     *
116
     * @var \League\Flysystem\FilesystemInterface
117
     */
118
    protected $filesystem;
119
120
    /**
121
     * The actual line number.
122
     *
123
     * @var integer
124
     */
125
    protected $lineNumber = 0;
126
127
    /**
128
     * The actual operation name.
129
     *
130
     * @var string
131
     */
132
    protected $operationName ;
133
134
    /**
135
     * The flag that stop's overserver execution on the actual row.
136
     *
137
     * @var boolean
138
     */
139
    protected $skipRow = false;
140
141
    /**
142
     * Stop's observer execution on the actual row.
143
     *
144
     * @return void
145
     */
146
    public function skipRow()
147
    {
148
        $this->skipRow = true;
149
    }
150
151
    /**
152
     * Return's the actual line number.
153
     *
154
     * @return integer The line number
155
     */
156
    public function getLineNumber()
157
    {
158
        return $this->lineNumber;
159
    }
160
161
    /**
162
     * Return's the actual operation name.
163
     *
164
     * @return string
165
     */
166
    public function getOperationName()
167
    {
168
        return $this->operationName;
169
    }
170
171
    /**
172
     * Set's the array containing header row.
173
     *
174
     * @param array $headers The array with the header row
175
     *
176
     * @return void
177
     */
178
    public function setHeaders(array $headers)
179
    {
180
        $this->headers = $headers;
181
    }
182
183
    /**
184
     * Return's the array containing header row.
185
     *
186
     * @return array The array with the header row
187
     */
188
    public function getHeaders()
189
    {
190
        return $this->headers;
191
    }
192
193
    /**
194
     * Queries whether or not the header with the passed name is available.
195
     *
196
     * @param string $name The header name to query
197
     *
198
     * @return boolean TRUE if the header is available, else FALSE
199
     */
200
    public function hasHeader($name)
201
    {
202
        return isset($this->headers[$name]);
203
    }
204
205
    /**
206
     * Return's the header value for the passed name.
207
     *
208
     * @param string $name The name of the header to return the value for
209
     *
210
     * @return mixed The header value
211
     * \InvalidArgumentException Is thrown, if the header with the passed name is NOT available
212
     */
213
    public function getHeader($name)
214
    {
215
216
        // query whether or not, the header is available
217
        if (isset($this->headers[$name])) {
218
            return $this->headers[$name];
219
        }
220
221
        // throw an exception, if not
222
        throw new \InvalidArgumentException(sprintf('Header %s is not available', $name));
223
    }
224
225
    /**
226
     * Add's the header with the passed name and position, if not NULL.
227
     *
228
     * @param string $name The header name to add
229
     *
230
     * @return integer The new headers position
231
     */
232
    public function addHeader($name)
233
    {
234
235
        // add the header
236
        $this->headers[$name] = $position = sizeof($this->headers);
237
238
        // return the new header's position
239
        return $position;
240
    }
241
242
    /**
243
     * Queries whether or not debug mode is enabled or not, default is TRUE.
244
     *
245
     * @return boolean TRUE if debug mode is enabled, else FALSE
246
     */
247
    public function isDebugMode()
248
    {
249
        return $this->getConfiguration()->isDebugMode();
250
    }
251
252
    /**
253
     * Set's the system configuration.
254
     *
255
     * @param \TechDivision\Import\Configuration\Subject $configuration The system configuration
256
     *
257
     * @return void
258
     */
259
    public function setConfiguration(SubjectConfigurationInterface $configuration)
260
    {
261
        $this->configuration = $configuration;
262
    }
263
264
    /**
265
     * Return's the system configuration.
266
     *
267
     * @return \TechDivision\Import\Configuration\SubjectInterface The system configuration
268
     */
269
    public function getConfiguration()
270
    {
271
        return $this->configuration;
272
    }
273
274
    /**
275
     * Set's the system logger.
276
     *
277
     * @param \Psr\Log\LoggerInterface $systemLogger The system logger
278
     *
279
     * @return void
280
     */
281
    public function setSystemLogger(LoggerInterface $systemLogger)
282
    {
283
        $this->systemLogger = $systemLogger;
284
    }
285
286
    /**
287
     * Return's the system logger.
288
     *
289
     * @return \Psr\Log\LoggerInterface The system logger instance
290
     */
291
    public function getSystemLogger()
292
    {
293
        return $this->systemLogger;
294
    }
295
296
    /**
297
     * Set's root directory for the virtual filesystem.
298
     *
299
     * @param string $rootDir The root directory for the virtual filesystem
300
     *
301
     * @return void
302
     */
303
    public function setRootDir($rootDir)
304
    {
305
        $this->rootDir = $rootDir;
306
    }
307
308
    /**
309
     * Return's the root directory for the virtual filesystem.
310
     *
311
     * @return string The root directory for the virtual filesystem
312
     */
313
    public function getRootDir()
314
    {
315
        return $this->rootDir;
316
    }
317
318
    /**
319
     * Set's the virtual filesystem instance.
320
     *
321
     * @param \League\Flysystem\FilesystemInterface $filesystem The filesystem instance
322
     *
323
     * @return void
324
     */
325
    public function setFilesystem(FilesystemInterface $filesystem)
326
    {
327
        $this->filesystem = $filesystem;
328
    }
329
330
    /**
331
     * Return's the virtual filesystem instance.
332
     *
333
     * @return \League\Flysystem\FilesystemInterface The filesystem instance
334
     */
335
    public function getFilesystem()
336
    {
337
        return $this->filesystem;
338
    }
339
340
    /**
341
     * Sets's the RegistryProcessor instance to handle the running threads.
342
     *
343
     * @param \TechDivision\Import\Services\RegistryProcessorInterface $registryProcessor The registry processor instance
344
     *
345
     * @return void
346
     */
347
    public function setRegistryProcessor(RegistryProcessorInterface $registryProcessor)
348
    {
349
        $this->registryProcessor = $registryProcessor;
350
    }
351
352
    /**
353
     * Return's the RegistryProcessor instance to handle the running threads.
354
     *
355
     * @return \TechDivision\Import\Services\RegistryProcessorInterface The registry processor instance
356
     */
357
    public function getRegistryProcessor()
358
    {
359
        return $this->registryProcessor;
360
    }
361
362
    /**
363
     * Set's the unique serial for this import process.
364
     *
365
     * @param string $serial The unique serial
366
     *
367
     * @return void
368
     */
369
    public function setSerial($serial)
370
    {
371
        $this->serial = $serial;
372
    }
373
374
    /**
375
     * Return's the unique serial for this import process.
376
     *
377
     * @return string The unique serial
378
     */
379
    public function getSerial()
380
    {
381
        return $this->serial;
382
    }
383
384
    /**
385
     * Set's the name of the file to import
386
     *
387
     * @param string $filename The filename
388
     *
389
     * @return void
390
     */
391
    public function setFilename($filename)
392
    {
393
        $this->filename = $filename;
394
    }
395
396
    /**
397
     * Return's the name of the file to import.
398
     *
399
     * @return string The filename
400
     */
401
    public function getFilename()
402
    {
403
        return $this->filename;
404
    }
405
406
    /**
407
     * Return's the source date format to use.
408
     *
409
     * @return string The source date format
410
     */
411
    public function getSourceDateFormat()
412
    {
413
        return $this->getConfiguration()->getSourceDateFormat();
414
    }
415
416
    /**
417
     * Return's the multiple field delimiter character to use, default value is comma (,).
418
     *
419
     * @return string The multiple field delimiter character
420
     */
421
    public function getMultipleFieldDelimiter()
422
    {
423
        return $this->getConfiguration()->getMultipleFieldDelimiter();
0 ignored issues
show
Bug introduced by
The method getMultipleFieldDelimiter() does not seem to exist on object<TechDivision\Impo...ation\SubjectInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
424
    }
425
426
    /**
427
     * Return's the initialized PDO connection.
428
     *
429
     * @return \PDO The initialized PDO connection
430
     */
431
    public function getConnection()
432
    {
433
        return $this->getProductProcessor()->getConnection();
0 ignored issues
show
Bug introduced by
The method getProductProcessor() does not seem to exist on object<TechDivision\Impo...bjects\AbstractSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
434
    }
435
436
    /**
437
     * Intializes the previously loaded global data for exactly one bunch.
438
     *
439
     * @return void
440
     * @see \Importer\Csv\Actions\ProductImportAction::prepare()
441
     */
442
    public function setUp()
443
    {
444
445
        // initialize the filesystems root directory
446
        $this->setRootDir(
447
            $this->getConfiguration()->getParam(ConfigurationKeys::ROOT_DIRECTORY, getcwd())
448
        );
449
450
        // initialize the filesystem
451
        $this->filesystem = new Filesystem(new Local($this->getRootDir()));
452
453
        // initialize the operation name
454
        $this->operationName = $this->getConfiguration()->getConfiguration()->getOperationName();
455
    }
456
457
    /**
458
     * This method tries to resolve the passed path and returns it. If the path
459
     * is relative, the actual working directory will be prepended.
460
     *
461
     * @param string $path The path to be resolved
462
     *
463
     * @return string The resolved path
464
     * @throws \InvalidArgumentException Is thrown, if the path can not be resolved
465
     */
466
    public function resolvePath($path)
467
    {
468
        // if we've an absolute path, return it immediately
469
        if ($this->getFilesystem()->has($path)) {
470
            return $path;
471
        }
472
473
        // try to prepend the actual working directory, assuming we've a relative path
474
        if ($this->getFilesystem()->has($path = getcwd() . DIRECTORY_SEPARATOR . $path)) {
475
            return $path;
476
        }
477
478
        // throw an exception if the passed directory doesn't exists
479
        throw new \InvalidArgumentException(
480
            sprintf('Directory %s doesn\'t exist', $path)
481
        );
482
    }
483
484
    /**
485
     * Clean up the global data after importing the variants.
486
     *
487
     * @return void
488
     */
489
    public function tearDown()
490
    {
491
492
        // load the registry processor
493
        $registryProcessor = $this->getRegistryProcessor();
494
495
        // update the source directory for the next subject
496
        $registryProcessor->mergeAttributesRecursive(
497
            $this->getSerial(),
498
            array(RegistryKeys::SOURCE_DIRECTORY => $this->getNewSourceDir())
499
        );
500
501
        // log a debug message with the new source directory
502
        $this->getSystemLogger()->debug(
503
            sprintf('Subject %s successfully updated source directory to %s', __CLASS__, $this->getNewSourceDir())
504
        );
505
    }
506
507
    /**
508
     * Return's the next source directory, which will be the target directory
509
     * of this subject, in most cases.
510
     *
511
     * @return string The new source directory
512
     */
513
    protected function getNewSourceDir()
514
    {
515
        return sprintf('%s/%s', $this->getConfiguration()->getTargetDir(), $this->getSerial());
516
    }
517
518
    /**
519
     * Register the passed observer with the specific type.
520
     *
521
     * @param \TechDivision\Import\Observers\ObserverInterface $observer The observer to register
522
     * @param string                                           $type     The type to register the observer with
523
     *
524
     * @return void
525
     */
526
    public function registerObserver(ObserverInterface $observer, $type)
527
    {
528
529
        // query whether or not the array with the callbacks for the
530
        // passed type has already been initialized, or not
531
        if (!isset($this->observers[$type])) {
532
            $this->observers[$type] = array();
533
        }
534
535
        // append the callback with the instance of the passed type
536
        $this->observers[$type][] = $observer;
537
    }
538
539
    /**
540
     * Register the passed callback with the specific type.
541
     *
542
     * @param \TechDivision\Import\Callbacks\CallbackInterface $callback The subject to register the callbacks for
543
     * @param string                                           $type     The type to register the callback with
544
     *
545
     * @return void
546
     */
547
    public function registerCallback(CallbackInterface $callback, $type)
548
    {
549
550
        // query whether or not the array with the callbacks for the
551
        // passed type has already been initialized, or not
552
        if (!isset($this->callbacks[$type])) {
553
            $this->callbacks[$type] = array();
554
        }
555
556
        // append the callback with the instance of the passed type
557
        $this->callbacks[$type][] = $callback;
558
    }
559
560
    /**
561
     * Return's the array with callbacks for the passed type.
562
     *
563
     * @param string $type The type of the callbacks to return
564
     *
565
     * @return array The callbacks
566
     */
567
    public function getCallbacksByType($type)
568
    {
569
570
        // initialize the array for the callbacks
571
        $callbacks = array();
572
573
        // query whether or not callbacks for the type are available
574
        if (isset($this->callbacks[$type])) {
575
            $callbacks = $this->callbacks[$type];
576
        }
577
578
        // return the array with the type's callbacks
579
        return $callbacks;
580
    }
581
582
    /**
583
     * Return's the array with the available observers.
584
     *
585
     * @return array The observers
586
     */
587
    public function getObservers()
588
    {
589
        return $this->observers;
590
    }
591
592
    /**
593
     * Return's the array with the available callbacks.
594
     *
595
     * @return array The callbacks
596
     */
597
    public function getCallbacks()
598
    {
599
        return $this->callbacks;
600
    }
601
602
    /**
603
     * Imports the content of the file with the passed filename.
604
     *
605
     * @param string $serial   The unique process serial
606
     * @param string $filename The filename to process
607
     *
608
     * @return void
609
     * @throws \Exception Is thrown, if the import can't be processed
610
     */
611
    public function import($serial, $filename)
612
    {
613
614
        try {
615
            // stop processing, if the filename doesn't match
616
            if (!$this->match($filename)) {
617
                return;
618
            }
619
620
            // load the system logger instance
621
            $systemLogger = $this->getSystemLogger();
622
623
            // prepare the flag filenames
624
            $inProgressFilename = sprintf('%s.inProgress', $filename);
625
            $importedFilename = sprintf('%s.imported', $filename);
626
            $failedFilename = sprintf('%s.failed', $filename);
627
628
            // query whether or not the file has already been imported
629
            if (is_file($failedFilename) ||
630
                is_file($importedFilename) ||
631
                is_file($inProgressFilename)
632
            ) {
633
                // log a debug message and exit
634
                $systemLogger->debug(sprintf('Import running, found inProgress file %s', $inProgressFilename));
635
                return;
636
            }
637
638
            // flag file as in progress
639
            touch($inProgressFilename);
640
641
            // track the start time
642
            $startTime = microtime(true);
643
644
            // initialize serial and filename
645
            $this->setSerial($serial);
646
            $this->setFilename($filename);
647
648
            // load the system logger
649
            $systemLogger = $this->getSystemLogger();
650
651
            // initialize the global global data to import a bunch
652
            $this->setUp();
653
654
            // initialize the lexer instance itself
655
            $lexer = new Lexer($this->getLexerConfig());
656
657
            // initialize the interpreter
658
            $interpreter = new Interpreter();
659
            $interpreter->addObserver(array($this, 'importRow'));
660
661
            // query whether or not we want to use the strict mode
662
            if (!$this->getConfiguration()->isStrictMode()) {
663
                $interpreter->unstrict();
664
            }
665
666
            // log a message that the file has to be imported
667
            $systemLogger->debug(sprintf('Now start importing file %s', $filename));
668
669
            // parse the CSV file to be imported
670
            $lexer->parse($filename, $interpreter);
671
672
            // track the time needed for the import in seconds
673
            $endTime = microtime(true) - $startTime;
674
675
            // clean up the data after importing the bunch
676
            $this->tearDown();
677
678
            // log a message that the file has successfully been imported
679
            $systemLogger->debug(sprintf('Succesfully imported file %s in %f s', $filename, $endTime));
680
681
            // rename flag file, because import has been successfull
682
            rename($inProgressFilename, $importedFilename);
683
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
684
        } catch (\Exception $e) {
685
            // rename the flag file, because import failed and write the stack trace
686
            rename($inProgressFilename, $failedFilename);
0 ignored issues
show
Bug introduced by
The variable $inProgressFilename does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $failedFilename does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
687
            file_put_contents($failedFilename, $e->__toString());
688
689
            // clean up the data after importing the bunch
690
            $this->tearDown();
691
692
            // re-throw the exception
693
            throw $e;
694
        }
695
    }
696
697
    /**
698
     * This method queries whether or not the passed filename matches
699
     * the pattern, based on the subjects configured prefix.
700
     *
701
     * @param string $filename The filename to match
702
     *
703
     * @return boolean TRUE if the filename matches, else FALSE
704
     */
705
    protected function match($filename)
706
    {
707
708
        // prepare the pattern to query whether the file has to be processed or not
709
        $pattern = sprintf('/^.*\/%s.*\\.csv$/', $this->getConfiguration()->getPrefix());
710
711
        // stop processing, if the filename doesn't match
712
        return (boolean) preg_match($pattern, $filename);
713
    }
714
715
    /**
716
     * Initialize and return the lexer configuration.
717
     *
718
     * @return \Goodby\CSV\Import\Standard\LexerConfig The lexer configuration
719
     */
720
    protected function getLexerConfig()
721
    {
722
723
        // initialize the lexer configuration
724
        $config = new LexerConfig();
725
726
        // query whether or not a delimiter character has been configured
727
        if ($delimiter = $this->getConfiguration()->getDelimiter()) {
728
            $config->setDelimiter($delimiter);
729
        }
730
731
        // query whether or not a custom escape character has been configured
732
        if ($escape = $this->getConfiguration()->getEscape()) {
733
            $config->setEscape($escape);
734
        }
735
736
        // query whether or not a custom enclosure character has been configured
737
        if ($enclosure = $this->getConfiguration()->getEnclosure()) {
738
            $config->setEnclosure($enclosure);
739
        }
740
741
        // query whether or not a custom source charset has been configured
742
        if ($fromCharset = $this->getConfiguration()->getFromCharset()) {
743
            $config->setFromCharset($fromCharset);
744
        }
745
746
        // query whether or not a custom target charset has been configured
747
        if ($toCharset = $this->getConfiguration()->getToCharset()) {
748
            $config->setToCharset($toCharset);
749
        }
750
751
        // return the lexer configuratio
752
        return $config;
753
    }
754
755
    /**
756
     * Imports the passed row into the database.
757
     *
758
     * If the import failed, the exception will be catched and logged,
759
     * but the import process will be continued.
760
     *
761
     * @param array $row The row with the data to be imported
762
     *
763
     * @return void
764
     */
765
    public function importRow(array $row)
766
    {
767
768
        // raise the line number and reset the skip row flag
769
        $this->lineNumber++;
770
        $this->skipRow = false;
771
772
        // initialize the headers with the columns from the first line
773
        if (sizeof($this->getHeaders()) === 0) {
774
            $this->setHeaders(array_flip($row));
775
            return;
776
        }
777
778
        // process the observers
779
        foreach ($this->getObservers() as $observers) {
780
            // invoke the pre-import/import and post-import observers
781
            foreach ($observers as $observer) {
782
                // query whether or not we have to skip the row
783
                if ($this->skipRow) {
784
                    break;
785
                }
786
                // if not, process the next observer
787
                if ($observer instanceof ObserverInterface) {
788
                    $row = $observer->handle($row);
0 ignored issues
show
Bug introduced by
The method handle() does not seem to exist on object<TechDivision\Impo...vers\ObserverInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
789
                }
790
            }
791
        }
792
793
        // log a debug message with the actual line nr/file information
794
        $this->getSystemLogger()->debug(
795
            sprintf(
796
                'Successfully processed row (operation: %s) in file %s on line %d',
797
                $this->operationName,
798
                $this->filename,
799
                $this->lineNumber
800
            )
801
        );
802
    }
803
}
804