Completed
Push — 15.x ( 39dd4d...e89609 )
by Tim
02:40
created

RawEntityLoader   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 9
lcom 2
cbo 3
dl 0
loc 94
ccs 0
cts 36
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 27 4
A loadDefaultValue() 0 21 3
A load() 0 4 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Loaders\RawEntityLoader
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 2020 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\Loaders;
22
23
use TechDivision\Import\Utils\MemberNames;
24
use TechDivision\Import\Connection\ConnectionInterface;
25
use TechDivision\Import\Services\ImportProcessorInterface;
26
27
/**
28
 * Loader for raw entities.
29
 *
30
 * @author    Tim Wagner <[email protected]>
31
 * @copyright 2020 TechDivision GmbH <[email protected]>
32
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
33
 * @link      https://github.com/techdivision/import
34
 * @link      http://www.techdivision.com
35
 */
36
class RawEntityLoader implements LoaderInterface
37
{
38
39
    /**
40
     * The connection instance.
41
     *
42
     * @var \TechDivision\Import\Connection\ConnectionInterface
43
     */
44
    protected $connection;
45
46
    /**
47
     * The column metadata loader instance.
48
     *
49
     * @var \TechDivision\Import\Loaders\LoaderInterface
50
     */
51
    protected $rawEntities = array();
52
53
    /**
54
     * Construct a new instance.
55
     *
56
     * @param \TechDivision\Import\Connection\ConnectionInterface    $connection           The DB connection instance used to load the table metadata
57
     * @param \TechDivision\Import\Loaders\LoaderInterface           $columnMetadataLoader The column metadata loader instance
58
     * @param \TechDivision\Import\Services\ImportProcessorInterface $importProcessor      The import processor instance
59
     */
60
    public function __construct(
61
        ConnectionInterface $connection,
62
        LoaderInterface $columnMetadataLoader,
63
        ImportProcessorInterface $importProcessor
64
    ) {
65
66
        // set the connection
67
        $this->connection = $connection;
68
69
        // load the available EAV entity types
70
        $eavEntityTypes = $importProcessor->getEavEntityTypes();
71
72
        // iterate over the entity types and create the raw entities
73
        foreach ($eavEntityTypes as $eavEntityType) {
74
            // load the columns from the metadata
75
            $columns = array_filter(
76
                $columnMetadataLoader->load($eavEntityType[MemberNames::ENTITY_TABLE]),
0 ignored issues
show
Unused Code introduced by
The call to LoaderInterface::load() has too many arguments starting with $eavEntityType[\TechDivi...berNames::ENTITY_TABLE].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
77
                function ($value) {
78
                    return $value['Key'] !== 'PRI' && $value['Null'] === 'NO' ;
79
                }
80
            );
81
            // initialize the raw entities and their default values, if available
82
            foreach ($columns as $column) {
83
                $this->rawEntities[$eavEntityType[MemberNames::ENTITY_TYPE_CODE]][$column['Field']] = $this->loadDefaultValue($column);
84
            }
85
        }
86
    }
87
88
    /**
89
     * Return's the default value for the passed column.
90
     *
91
     * @param array $column The column to return the default value for
92
     *
93
     * @return string|null The default value for the passed column
94
     */
95
    protected function loadDefaultValue(array $column)
96
    {
97
98
        // load the default value
99
        $default = $column['Default'];
100
101
        // if a default value has been found
102
        if ($default === null) {
103
            return;
104
        }
105
106
        try {
107
            // try to load it resolve it by executing a select statement (assuming it is an MySQL expression)
108
            $row = $this->connection->query(sprintf('SELECT %s()', $default))->fetch(\PDO::FETCH_ASSOC);
109
            return reset($row);
110
        } catch (\PDOException $pdoe) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
111
        }
112
113
        // return the default value
114
        return $default;
115
    }
116
117
    /**
118
     * Loads and returns data.
119
     *
120
     * @param string|null $entityTypeCode The table name to return the list for
121
     * @param array       $data           An array with data that will be used to initialize the raw entity with
122
     *
123
     * @return \ArrayAccess The array with the raw data
124
     */
125
    public function load($entityTypeCode = null, array $data = array())
126
    {
127
        return isset($this->rawEntities[$entityTypeCode]) ? array_merge($this->rawEntities[$entityTypeCode], $data) : $data;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return isset($this->rawE...eCode], $data) : $data; (array) is incompatible with the return type declared by the interface TechDivision\Import\Loaders\LoaderInterface::load of type ArrayAccess.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
128
    }
129
}
130