]> git.mxchange.org Git - core.git/blob - framework/main/classes/database/class_BaseDatabaseWrapper.php
Continued:
[core.git] / framework / main / classes / database / class_BaseDatabaseWrapper.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Database\Frontend;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Criteria\Criteria;
8 use Org\Mxchange\CoreFramework\Criteria\Storing\StoreableCriteria;
9 use Org\Mxchange\CoreFramework\Database\Backend\BaseDatabaseBackend;
10 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
11 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
12
13 /**
14  * A generic database wrapper
15  *
16  * @author              Roland Haeder <webmaster@shipsimu.org>
17  * @version             0.0.0
18  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
19  * @license             GNU GPL 3.0 or any newer version
20  * @link                http://www.shipsimu.org
21  *
22  * This program is free software: you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation, either version 3 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program. If not, see <http://www.gnu.org/licenses/>.
34  */
35 abstract class BaseDatabaseWrapper extends BaseFrameworkSystem {
36         /**
37          * Cache instance
38          */
39         private $cacheInstance = NULL;
40
41         /**
42          * Current table name to use
43          */
44         private $tableName = 'unknown';
45
46         /**
47          * Protected constructor
48          *
49          * @return      void
50          */
51         protected function __construct ($class) {
52                 // Call parent constructor
53                 parent::__construct($class);
54
55                 // Initialize the cache instance
56                 $this->initCacheInstance();
57         }
58
59         /**
60          * Initializes the cache instance with a new object
61          *
62          * @return      void
63          */
64         private final function initCacheInstance () {
65                 // Is the cache enabled?
66                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) {
67                         // Set the new instance
68                         $this->cacheInstance = CacheFactory::getFactory()->createConfiguredCache();
69                 } // END - if
70         }
71
72         /**
73          * Setter for table name
74          *
75          * @param       $tableName      Name of table name to set
76          * @return      void
77          */
78         protected final function setTableName ($tableName) {
79                 $this->tableName = (string) $tableName;
80         }
81
82         /**
83          * Getter for table name
84          *
85          * @return      $tableName      Name of table name to set
86          */
87         protected final function getTableName () {
88                 return $this->tableName;
89         }
90
91         /**
92          * 'Inserts' a data set instance into a local file database folder
93          *
94          * @param       $dataSetInstance        A storeable data set
95          * @param       $onlyKeys                       Only use these keys for a cache key
96          * @return      void
97          */
98         protected function queryInsertDataSet (StoreableCriteria $dataSetInstance, array $onlyKeys = []) {
99                 // Default cache key is NULL
100                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: dataSetInstance=%s,onlyKeys()=%d - CALLED!', $dataSetInstance->__toString(), count($onlyKeys)));
101                 $cacheKey = NULL;
102
103                 // Is cache enabled?
104                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) {
105                         // First get a key suitable for our cache and extend it with this class name
106                         $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
107                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
108                 } // END - if
109
110                 // Does this key exists in cache?
111                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: cacheKey[%s]=%s', gettype($cacheKey), $cacheKey));
112                 if ((FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
113                         // Purge the cache
114                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: Calling this->cacheInstance->purgeOffset(%s) ...', $cacheKey));
115                         $this->cacheInstance->purgeOffset($cacheKey);
116                 } // END - if
117
118                 // Handle it over to the middleware
119                 FrameworkBootstrap::getDatabaseInstance()->queryInsertDataSet($dataSetInstance);
120
121                 // Trace message
122                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: EXIT!');
123         }
124
125         /**
126          * 'Updates' a data set instance with a database layer
127          *
128          * @param       $dataSetInstance        A storeable data set
129          * @param       $onlyKeys                       Only use these keys for a cache key
130          * @return      void
131          */
132         protected function queryUpdateDataSet (StoreableCriteria $dataSetInstance, array $onlyKeys = []) {
133                 // Init cache key
134                 $cacheKey = NULL;
135
136                 // Is cache enabled?
137                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) {
138                         // First get a key suitable for our cache and extend it with this class name
139                         $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
140                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
141                 } // END - if
142
143                 // Does this key exists in cache?
144                 if ((FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
145                         // Purge the cache
146                         $this->cacheInstance->purgeOffset($cacheKey);
147                 } // END - if
148
149                 // Handle it over to the middleware
150                 FrameworkBootstrap::getDatabaseInstance()->queryUpdateDataSet($dataSetInstance);
151         }
152
153         /**
154          * Getter for index key
155          *
156          * @return      $indexKey       Index key
157          */
158         public final function getIndexKey () {
159                 return FrameworkBootstrap::getDatabaseInstance()->getIndexKey();
160         }
161
162         /**
163          * Getter for last exception
164          *
165          * @return      $lastException  Last exception or NULL if none occured
166          */
167         public final function getLastException () {
168                 return FrameworkBootstrap::getDatabaseInstance()->getLastException();
169         }
170
171         /**
172          * Do a "select" query on the current table with the given search criteria and
173          * store it in cache for later usage
174          *
175          * @param       $criteriaInstance       An instance of a Criteria class
176          * @param       $onlyKeys                       Only use these keys for a cache key
177          * @return      $resultInstance         An instance of a database result class
178          */
179         public function doSelectByCriteria (Criteria $criteriaInstance, array $onlyKeys = []) {
180                 // Default cache key if cache is not enabled
181                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: criteriaInstance=%s,onlyKeys()=%d - CALLED!', $criteriaInstance->__toString(), count($onlyKeys)));
182                 $cacheKey = NULL;
183                 $result = [];
184
185                 // Is the cache enabled?
186                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) {
187                         // First get a key suitable for our cache and extend it with this class name
188                         $cacheKey = $this->getCacheKeyByCriteria($criteriaInstance, $onlyKeys);
189                 } // END - if
190
191                 // Does this key exists in cache?
192                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: cacheKey[%s]=%s', gettype($cacheKey), $cacheKey));
193                 if ((FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey, BaseDatabaseBackend::RESULT_INDEX_ROWS, 1))) {
194                         // Then use this result
195                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: Cache used for cacheKey=%s', $cacheKey));
196                         $result = $this->cacheInstance->offsetGet($cacheKey);
197                 } else {
198                         // Now it's time to ask the database layer for this select statement
199                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: Quering database, cacheKey=%s ...', $cacheKey));
200                         $result = FrameworkBootstrap::getDatabaseInstance()->doSelectByTableCriteria($this->getTableName(), $criteriaInstance);
201
202                         // Cache the result if not null
203                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: result[]=%s', gettype($result)));
204                         if (!is_null($result)) {
205                                 // Is cache enabled?
206                                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('database_cache_enabled') === true) {
207                                         // A valid result has returned from the database layer
208                                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: Setting cacheKey=%s with result()=%d entries', $cacheKey, count($result)));
209                                         $this->cacheInstance->offsetSet($cacheKey, $result);
210                                 } // END - if
211                         } else {
212                                 // This invalid result must be wrapped
213                                 $result = array(
214                                         BaseDatabaseBackend::RESULT_INDEX_STATUS    => 'invalid',
215                                         BaseDatabaseBackend::RESULT_INDEX_EXCEPTION => FrameworkBootstrap::getDatabaseInstance()->getLastException()
216                                 );
217                         }
218                 }
219
220                 // Create an instance of a CachedDatabaseResult class with the given result
221                 // @TODO Minor: Update above comment to e.g. BaseDatabaseResult
222                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: result[%s]=%s,result[%s]?=%d,result[%s]?=%d', BaseDatabaseBackend::RESULT_INDEX_STATUS, $result[BaseDatabaseBackend::RESULT_INDEX_STATUS], BaseDatabaseBackend::RESULT_INDEX_ROWS, isset($result[BaseDatabaseBackend::RESULT_INDEX_ROWS]), BaseDatabaseBackend::RESULT_INDEX_EXCEPTION, isset($result[BaseDatabaseBackend::RESULT_INDEX_EXCEPTION])));
223                 $resultInstance = ObjectFactory::createObjectByConfiguredName('database_result_class', array($result));
224
225                 // And return the instance
226                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-WRAPPER: resultInstance=%s - EXIT!', $resultInstance->__toString()));
227                 return $resultInstance;
228         }
229
230         /**
231          * Count the numbers of rows we shall receive
232          *
233          * @param       $criteriaInstance       An instance of a Criteria class
234          * @param       $onlyKeys                       Only use these keys for a cache key
235          * @return      $numRows                        Numbers of rows of database entries
236          */
237         public function doSelectCountByCriteria (Criteria $criteriaInstance, array $onlyKeys = []) {
238                 // Total numbers is -1 so we can distinglish between failed and valid queries
239                 $numRows = 0;
240
241                 // Get the result from above method
242                 $resultInstance = $this->doSelectByCriteria($criteriaInstance, $onlyKeys);
243
244                 // Was that query fine?
245                 if ($resultInstance->ifStatusIsOkay()) {
246                         // Then get the number of rows
247                         $numRows = $resultInstance->getAffectedRows();
248
249                         // Debug message
250                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: numRows=' . $numRows);
251                 } // END - if
252
253                 // Return the result
254                 return $numRows;
255         }
256
257         /**
258          * Getter for primary key used in wrapped table
259          *
260          * @return      $primaryKey             Primary key used in wrapped table
261          */
262         public final function getPrimaryKeyValue () {
263                 // Get the table name and a database instance and ask for it
264                 $primaryKey = FrameworkBootstrap::getDatabaseInstance()->getPrimaryKeyOfTable($this->getTableName());
265
266                 // Return value
267                 return $primaryKey;
268         }
269
270         /**
271          * Count rows of this table
272          *
273          * @return      $count  Count of total rows in this table
274          */
275         public final function countTotalRows () {
276                 // Get the table name and a database instance and ask for it
277                 $count = FrameworkBootstrap::getDatabaseInstance()->countTotalRows($this->getTableName());
278
279                 // Return value
280                 return $count;
281         }
282
283         /**
284          * Removes non-public data from given array.
285          *
286          * @param       $data   An array with possible non-public data that needs to be removed.
287          * @return      $data   A cleaned up array with only public data.
288          */
289         public function removeNonPublicDataFromArray (array $data) {
290                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: Calling FrameworkBootstrap::getDatabaseInstance()->removeNonPublicDataFromArray(data) ...');
291                 $data = FrameworkBootstrap::getDatabaseInstance()->removeNonPublicDataFromArray($data);
292
293                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: data[]=' . gettype($data));
294                 return $data;
295         }
296
297 }