Completed
Push — master ( 6a811e...c52182 )
by Hong
02:35
created

Driver::realCommit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Db
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Db\Driver\Pdo;
16
17
use Phossa2\Db\Message\Message;
18
use Phossa2\Db\Driver\DriverAbstract;
19
use Phossa2\Db\Exception\LogicException;
20
use Phossa2\Db\Interfaces\StatementInterface;
21
22
/**
23
 * Driver
24
 *
25
 * PDO driver
26
 *
27
 * @package Phossa2\Db
28
 * @author  Hong Zhang <[email protected]>
29
 * @see     DriverAbstract
30
 * @version 2.0.0
31
 * @since   2.0.0 added
32
 */
33
class Driver extends DriverAbstract
34
{
35
    /**
36
     * the connection link
37
     *
38
     * @var    \PDO
39
     * @access protected
40
     */
41
    protected $link;
42
43
    /**
44
     * Default PDO attributes
45
     *
46
     * @var    array
47
     * @access protected
48
     */
49
    protected $attributes = [
50
        'PDO::ATTR_ERRMODE'             => \PDO::ERRMODE_SILENT,
51
        'PDO::ATTR_CASE'                => \PDO::CASE_NATURAL,
52
        'PDO::ATTR_ORACLE_NULLS'        => \PDO::NULL_NATURAL,
53
        'PDO::ATTR_DEFAULT_FETCH_MODE'  => \PDO::FETCH_ASSOC,
54
        'PDO::ATTR_EMULATE_PREPARES'    => false,
55
    ];
56
57
    /**
58
     * Driver constructor
59
     *
60
     * @param  array $connectInfo
61
     * @param  StatementInterface $statementPrototype
62
     * @throws InvalidArgumentException if link type not right
63
     * @throws LogicException driver specific extension not loaded
64
     * @access public
65
     */
66
    public function __construct(
67
        $connectInfo,
68
        StatementInterface $statementPrototype = null
69
    ) {
70
        parent::__construct($connectInfo);
71
72
        // set prototypes
73
        $this->statement_prototype = $statementPrototype ?: new Statement();
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79
    protected function extensionLoaded()/*# : bool */
80
    {
81
        return extension_loaded('PDO');
82
    }
83
84
    /**
85
     * {@inheritDoc}
86
     */
87
    protected function realLastId($name)
88
    {
89
        return $this->link->lastInsertId($name);
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     */
95
    protected function realConnect(array $parameters)
96
    {
97
        $this->link = new \PDO(
98
            isset($parameters['dsn']) ? $parameters['dsn'] : '',
99
            isset($parameters['username']) ? $parameters['username'] : 'root',
100
            isset($parameters['password']) ? $parameters['password'] : null,
101
            isset($parameters['options']) ? $parameters['options'] : null
102
        );
103
104
        // set attributes
105
        if (!empty($this->attributes)) {
106
            foreach ($this->attributes as $attr => $val) {
107
                $this->realSetAttribute($attr, $val);
108
            }
109
        }
110
111
        return $this;
112
    }
113
114
    /**
115
     * Disconnect the \PDO link
116
     *
117
     * {@inheritDoc}
118
     */
119
    protected function realDisconnect()
120
    {
121
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Phossa2\Db\Driver\Pdo\Driver) is incompatible with the return type declared by the abstract method Phossa2\Db\Driver\DriverAbstract::realDisconnect of type Phossa2\Db\Traits\ConnectTrait.

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...
122
    }
123
124
    /**
125
     * {@inheritDoc}
126
     */
127
    protected function realPing()/*# : bool */
128
    {
129
        try {
130
            return (bool) $this->link->query('SELECT 1');
131
        } catch (\Exception $e) {
132
            return false;
133
        }
134
    }
135
136
    /**
137
     * {@inheritDoc}
138
     */
139 View Code Duplication
    protected function realSetAttribute(/*# string */ $attribute, $value)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        if (is_string($attribute)) {
142
            if (defined($attribute)) {
143
                $this->link->setAttribute(constant($attribute), $value);
144
            } else {
145
                throw new LogicException(
146
                    Message::get(Message::DB_ATTRIBUTE_UNKNOWN, $attribute),
147
                    Message::DB_ATTRIBUTE_UNKNOWN
148
                );
149
            }
150
        } else {
151
            $this->link->setAttribute($attribute, $value);
152
        }
153
        return $this;
154
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159 View Code Duplication
    protected function realGetAttribute(/*# string */ $attribute)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
    {
161
        if (is_string($attribute)) {
162
            if (defined($attribute)) {
163
                return $this->link->getAttribute(constant($attribute));
164
            } else {
165
                throw new LogicException(
166
                    Message::get(Message::DB_ATTRIBUTE_UNKNOWN, $attribute),
167
                    Message::DB_ATTRIBUTE_UNKNOWN
168
                );
169
            }
170
        } else {
171
            return $this->link->getAttribute($attribute);
172
        }
173
    }
174
175
    /**
176
     * {@inheritDoc}
177
     */
178
    protected function realBegin()
179
    {
180
        $this->link->beginTransaction();
181
        return $this;
182
    }
183
184
    /**
185
     * {@inheritDoc}
186
     */
187
    protected function realCommit()
188
    {
189
        $this->link->commit();
190
        return $this;
191
    }
192
193
    /**
194
     * {@inheritDoc}
195
     */
196
    protected function realRollback()
197
    {
198
        $this->link->rollBack();
199
        return $this;
200
    }
201
}
202