Completed
Push — master ( 37f54e...a8ce98 )
by Hong
02:32
created

StatementAbstract::__destruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
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;
16
17
use Phossa2\Db\Message\Message;
18
use Phossa2\Db\Traits\DriverAwareTrait;
19
use Phossa2\Shared\Base\ObjectAbstract;
20
use Phossa2\Db\Interfaces\ResultInterface;
21
use Phossa2\Db\Exception\RuntimeException;
22
use Phossa2\Db\Exception\NotFoundException;
23
use Phossa2\Db\Interfaces\StatementInterface;
24
25
/**
26
 * StatementAbstract
27
 *
28
 * @package Phossa2\Db
29
 * @author  Hong Zhang <[email protected]>
30
 * @see     ObjectAbstract
31
 * @see     StatementInterface
32
 * @version 2.0.0
33
 * @since   2.0.0 added
34
 */
35
abstract class StatementAbstract extends ObjectAbstract implements StatementInterface
36
{
37
    use DriverAwareTrait;
38
39
    /**
40
     * prepared statement
41
     *
42
     * @var    mixed
43
     * @access protected
44
     */
45
    protected $prepared;
46
47
    /**
48
     * Result prototype
49
     *
50
     * @var    ResultInterface
51
     * @access protected
52
     */
53
    protected $result_prototype;
54
55
    /**
56
     * @var    ResultInterface
57
     * @access protected
58
     */
59
    protected $result;
60
61
    /**
62
     * Desctructor
63
     *
64
     * @access public
65
     */
66
    public function __destruct()
67
    {
68
        $this->close();
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function prepare(/*# string */ $sql)/*# : bool */
75
    {
76
        if (null === $this->prepared) {
77
            try {
78
                $res = $this->realPrepare($this->getDriver()->getLink(), $sql);
79
                if (false !== $res) {
80
                    $this->prepared = $res;
81
                    $this->getDriver()->getProfiler()->setSql($sql);
82
                    return true;
83
                }
84
            } catch (\Exception $e) {
85
                throw new RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
86
            }
87
            throw new RuntimeException(
88
                Message::get(Message::DB_STMT_PREPARE_FAIL, $sql),
89
                Message::DB_STMT_PREPARE_FAIL
90
            );
91
        }
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public function execute(array $parameters = [])/*# : bool */
98
    {
99
        $this->checkPreparation(); // must be prepared
100
        $this->result = null; // close result if any
101
102
        // int profiler
103
        $time = microtime(true);
104
        $this->getDriver()->getProfiler()->setParameters($parameters);
105
106
        try {
107
            if ($this->realExecute($parameters)) {
108
                $result = clone $this->result_prototype;
109
                $this->result = $result($this->prepared);
110
                $this->getDriver()->getProfiler()
111
                    ->setExecutionTime(microtime(true) - $time);
112
                return true;
113
            }
114
        } catch (\Exception $e) {
115
            throw new RuntimeException($e->getMessage(), (int) $e->getCode(), $e);
116
        }
117
        throw new RuntimeException(
118
            Message::get(
119
                Message::DB_STMT_EXECUTE_FAIL,
120
                $this->getDriver()->getProfiler()->getSql()
121
            ), Message::DB_STMT_EXECUTE_FAIL
122
        );
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function getResult()/*# : ResultInterface */
129
    {
130
        if (null === $this->result) {
131
            throw new NotFoundException(
132
                Message::get(Message::DB_STMT_NO_RESULT),
133
                Message::DB_STMT_NO_RESULT
134
            );
135
        }
136
        return $this->result;
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     */
142
    public function close()
143
    {
144
        if ($this->prepared) {
145
            $this->realClose($this->prepared);
146
            $this->result = null;
147
        }
148
    }
149
150
    /**
151
     * Throw exception if not prepared
152
     *
153
     * @throws RuntimeException
154
     * @access protected
155
     */
156
    protected function checkPreparation()
157
    {
158
        if (null === $this->prepared) {
159
            throw new RuntimeException(
160
                Message::get(Message::DB_STMT_NOTPREPARED),
161
                Message::DB_STMT_NOTPREPARED
162
            );
163
        }
164
    }
165
166
    /**
167
     * Driver specific prepare statement
168
     *
169
     * @param  mixed $link db link resource
170
     * @param  string $sql
171
     * @return mixed
172
     * @throws RuntimeException
173
     * @access protected
174
     */
175
    abstract protected function realPrepare($link, /*# string */ $sql);
176
177
    /**
178
     * Driver specific statement execution
179
     *
180
     * @param  array $parameters
181
     * @return bool
182
     * @throws RuntimeException
183
     * @access protected
184
     */
185
    abstract protected function realExecute(array $parameters)/*# : bool */;
186
187
    /**
188
     * Close statement
189
     *
190
     * @param  mixed prepared low-level statement
191
     * @access protected
192
     */
193
    abstract protected function realClose($stmt);
194
}
195