Subversion Repositories oidplus

Rev

Rev 1152 | Rev 1157 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1152 Rev 1156
Line 34... Line 34...
34
         * @return int
34
         * @return int
35
         */
35
         */
36
        abstract protected function do_num_rows(): int;
36
        abstract protected function do_num_rows(): int;
37
 
37
 
38
        /**
38
        /**
-
 
39
         * @var array|null
-
 
40
         */
-
 
41
        protected $prefetchedArray = null;
-
 
42
 
-
 
43
        /**
-
 
44
         * @var int
-
 
45
         */
-
 
46
        protected $countAlreadyFetched = 0;
-
 
47
 
-
 
48
        /**
-
 
49
         * Please override this method if the database drive can perform a "fetch all" in its own way
-
 
50
         *
-
 
51
         * @return void
-
 
52
         * @throws OIDplusConfigInitializationException
-
 
53
         * @throws OIDplusException
-
 
54
         * @throws \ReflectionException
-
 
55
         */
-
 
56
        public function prefetchAll() {
-
 
57
                if (!is_null($this->prefetchedArray)) return;
-
 
58
                $pfa = array();
-
 
59
                while ($row = $this->fetch_array()) {
-
 
60
                        $pfa[] = $row; // you may not edit $this->prefetchedArray at this step, because $this->>fetch_array() checks it
-
 
61
                        $this->countAlreadyFetched--; // because fetch_array() increases $this->countAlreadyFetched, we need to revert it
-
 
62
                }
-
 
63
                $this->prefetchedArray = $pfa;
-
 
64
        }
-
 
65
 
-
 
66
        /**
39
         * @return int
67
         * @return int
-
 
68
         * @throws OIDplusConfigInitializationException
-
 
69
         * @throws OIDplusException
40
         */
70
         */
41
        public final function num_rows(): int {
71
        public final function num_rows(): int {
42
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
72
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
-
 
73
 
-
 
74
                if (!is_null($this->prefetchedArray)) {
-
 
75
                        return count($this->prefetchedArray) + $this->countAlreadyFetched;
-
 
76
                }
-
 
77
 
43
                return $this->do_num_rows();
78
                $ret = $this->do_num_rows();
-
 
79
 
-
 
80
                if ($ret === -1) throw new OIDplusException(_L('The database driver has problems with "%1"','num_rows'));
-
 
81
 
-
 
82
                return $ret;
-
 
83
        }
-
 
84
 
-
 
85
        /**
-
 
86
         * Plugins can override and extend this method. It post-processes contents of fetch_array() and fetch_object()
-
 
87
         * to fix various issues with database drivers.
-
 
88
         *
-
 
89
         * @param array|object &$ret
-
 
90
         * @return void
-
 
91
         */
-
 
92
        protected function fixFields(&$ret) {
-
 
93
                // ODBC gives bit(1) as binary, MySQL as integer and PDO as string.
-
 
94
                // We'll do it like MySQL does, even if ODBC is actually more correct.
-
 
95
                foreach ($ret as &$value) {
-
 
96
                        if ($value === chr(0)) $value = 0;
-
 
97
                        if ($value === chr(1)) $value = 1;
-
 
98
                }
-
 
99
 
-
 
100
                // Oracle returns $ret['VALUE'] because unquoted column-names are always upper-case
-
 
101
                // We can't quote every single column throughout the whole program, so we use this workaround...
-
 
102
                if (is_array($ret)) {
-
 
103
                        $keys = array_keys($ret);
-
 
104
                        foreach ($keys as $key) {
-
 
105
                                $ret[strtolower($key)] = $ret[$key];
-
 
106
                                $ret[strtoupper($key)] = $ret[$key];
-
 
107
                        }
-
 
108
                } else if (is_object($ret)) {
-
 
109
                        foreach ($ret as $name => $val) {
-
 
110
                                $ret->{strtoupper($name)} = $val;
-
 
111
                                $ret->{strtolower($name)} = $val;
-
 
112
                        }
-
 
113
                }
44
        }
114
        }
45
 
115
 
46
        /**
116
        /**
-
 
117
         * Please override do_fetch_object(), do_fetch_array(), or both.
47
         * @return array|null
118
         * @return array|null
48
         */
119
         */
49
        protected function do_fetch_array()/*: ?array*/ {
120
        protected function do_fetch_array()/*: ?array*/ {
50
                assert(false);
121
                assert(false);
51
                return null;
122
                return null;
52
        }
123
        }
53
 
124
 
54
        /**
125
        /**
55
         * @return array|null
126
         * @return array|null
-
 
127
         * @throws OIDplusConfigInitializationException
-
 
128
         * @throws OIDplusException
-
 
129
         * @throws \ReflectionException
56
         */
130
         */
57
        public final function fetch_array()/*: ?array*/ {
131
        public final function fetch_array()/*: ?array*/ {
58
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
132
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
-
 
133
                if (!is_null($this->prefetchedArray)) {
-
 
134
                        // Prefetched value exists. Use it.
-
 
135
                        $ary = array_shift($this->prefetchedArray);
59
 
136
                } else {
60
                $reflector = new \ReflectionMethod($this, 'do_fetch_array');
137
                        $reflector = new \ReflectionMethod($this, 'do_fetch_array');
61
                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
138
                        $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
-
 
139
                        if ($isImplemented) {
-
 
140
                                // do_fetch_array() is implemented. Use it.
62
                if ($isImplemented) return $this->do_fetch_array();
141
                                $ary = $this->do_fetch_array();
63
 
142
                        } else {
-
 
143
                                // Use the implementation of do_fetch_object()
64
                $reflector = new \ReflectionMethod($this, 'do_fetch_object');
144
                                $reflector = new \ReflectionMethod($this, 'do_fetch_object');
65
                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
145
                                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
66
                if (!$isImplemented) {
146
                                if (!$isImplemented) {
67
                        throw new OIDplusException(_L("Class %1 is erroneous: At least one fetch-method needs to be overridden", get_class($this)));
147
                                        throw new OIDplusException(_L("Class %1 is erroneous: At least one fetch-method needs to be overridden", get_class($this)));
68
                }
148
                                }
69
 
-
 
70
                // Convert object to array
-
 
71
                $obj = $this->do_fetch_object();
149
                                $obj = $this->do_fetch_object();
72
                if (!$obj) return null;
150
                                $ary = is_null($obj) ? null : stdobj_to_array($obj);
-
 
151
                        }
-
 
152
                }
73
                $ary = array();
153
                if (!is_null($ary)) {
74
                foreach ($obj as $name => $val) {
154
                        $this->countAlreadyFetched++;
75
                        $ary[$name] = $val;
155
                        $this->fixFields($ary);
76
                }
156
                }
77
                return $ary;
157
                return $ary;
78
        }
158
        }
79
 
159
 
80
        /**
160
        /**
-
 
161
         * Please override do_fetch_object(), do_fetch_array(), or both.
81
         * @return object|null
162
         * @return object|null
82
         */
163
         */
83
        protected function do_fetch_object()/*: ?object*/ {
164
        protected function do_fetch_object()/*: ?\stdClass*/ {
84
                assert(false);
165
                assert(false);
85
                return null;
166
                return null;
86
        }
167
        }
87
 
168
 
88
        /**
169
        /**
89
         * @return object|null
170
         * @return object|null
-
 
171
         * @throws OIDplusConfigInitializationException
-
 
172
         * @throws OIDplusException
-
 
173
         * @throws \ReflectionException
90
         */
174
         */
91
        public final function fetch_object()/*: ?object*/ {
175
        public final function fetch_object()/*: ?\stdClass*/ {
92
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
176
                if (!$this->containsResultSet()) throw new OIDplusException(_L('The query has returned no result set (i.e. it was not a SELECT query)'));
-
 
177
                if (!is_null($this->prefetchedArray)) {
-
 
178
                        // Prefetched value exists. Use it.
-
 
179
                        $ary = array_shift($this->prefetchedArray);
-
 
180
                        $obj = is_null($ary) ? null : array_to_stdobj($ary);
93
 
181
                } else {
94
                $reflector = new \ReflectionMethod($this, 'do_fetch_object');
182
                        $reflector = new \ReflectionMethod($this, 'do_fetch_object');
95
                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
183
                        $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
-
 
184
                        if ($isImplemented) {
-
 
185
                                // do_fetch_object() is implemented. Use it.
96
                if ($isImplemented) return $this->do_fetch_object();
186
                                $obj = $this->do_fetch_object();
97
 
187
                        } else {
-
 
188
                                // Use the implementation of do_fetch_array()
98
                $reflector = new \ReflectionMethod($this, 'do_fetch_array');
189
                                $reflector = new \ReflectionMethod($this, 'do_fetch_array');
99
                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
190
                                $isImplemented = ($reflector->getDeclaringClass()->getName() !== self::class);
100
                if (!$isImplemented) {
191
                                if (!$isImplemented) {
101
                        throw new OIDplusException(_L("Class %1 is erroneous: At least one fetch-method needs to be overridden", get_class($this)));
192
                                        throw new OIDplusException(_L("Class %1 is erroneous: At least one fetch-method needs to be overridden", get_class($this)));
102
                }
193
                                }
103
 
-
 
104
                // Convert array of object
-
 
105
                $ary = $this->do_fetch_array();
194
                                $ary = $this->do_fetch_array();
106
                if (!$ary) return null;
195
                                $obj = is_null($ary) ? null : array_to_stdobj($ary);
-
 
196
                        }
-
 
197
                }
107
                $obj = new \stdClass;
198
                if (!is_null($obj)) {
108
                foreach ($ary as $name => $val) {
199
                        $this->countAlreadyFetched++;
109
                        $obj->$name = $val;
200
                        $this->fixFields($obj);
110
                }
201
                }
111
                return $obj;
202
                return $obj;
112
        }
203
        }
113
 
204
 
114
        /**
205
        /**
115
         * The any() function returns true if there is at least one
206
         * The any() function returns true if there is at least one
116
         * row in the section. By default, num_rows() will be used.
207
         * row in the section. By default, num_rows() will be used.
117
         * Plugins can override this method if they have a possibility
208
         * Plugins can override this method if they have a possibility
118
         * of making this functionality more efficient.
209
         * of making this functionality more efficient.
-
 
210
         *
119
         * @return bool
211
         * @return bool
-
 
212
         * @throws OIDplusException
120
         */
213
         */
121
        public function any(): bool {
214
        public function any(): bool {
122
                return $this->num_rows() > 0;
215
                return $this->num_rows() > 0;
123
        }
216
        }
-
 
217
 
-
 
218
        /**
-
 
219
         * @param string $dbField
-
 
220
         * @return void
-
 
221
         * @throws OIDplusConfigInitializationException
-
 
222
         * @throws OIDplusException
-
 
223
         * @throws \ReflectionException
-
 
224
         */
-
 
225
        public final function naturalSortByField(string $dbField) {
-
 
226
                if (is_null($this->prefetchedArray)) {
-
 
227
                        $this->prefetchAll();
-
 
228
                }
-
 
229
 
-
 
230
                // Sort $this->prefetchedArray by field $dbField
-
 
231
                natsort_field($this->prefetchedArray, $dbField);
-
 
232
        }
124
}
233
}