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 - 2019 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 ($this->getConfigInstance()->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 = array()) {
99                 // Default cache key is NULL
100                 $cacheKey = NULL;
101
102                 // Is cache enabled?
103                 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
104                         // First get a key suitable for our cache and extend it with this class name
105                         $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
106                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
107                 } // END - if
108
109                 // Does this key exists in cache?
110                 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
111                         // Purge the cache
112                         $this->cacheInstance->purgeOffset($cacheKey);
113                 } // END - if
114
115                 // Handle it over to the middleware
116                 FrameworkBootstrap::getDatabaseInstance()->queryInsertDataSet($dataSetInstance);
117         }
118
119         /**
120          * 'Updates' a data set instance with a database layer
121          *
122          * @param       $dataSetInstance        A storeable data set
123          * @param       $onlyKeys                       Only use these keys for a cache key
124          * @return      void
125          */
126         protected function queryUpdateDataSet (StoreableCriteria $dataSetInstance, array $onlyKeys = array()) {
127                 // Init cache key
128                 $cacheKey = NULL;
129
130                 // Is cache enabled?
131                 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
132                         // First get a key suitable for our cache and extend it with this class name
133                         $cacheKey = $this->getCacheKeyByCriteria($dataSetInstance, $onlyKeys);
134                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Using cache key ' . $cacheKey . ' for purging ...');
135                 } // END - if
136
137                 // Does this key exists in cache?
138                 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey))) {
139                         // Purge the cache
140                         $this->cacheInstance->purgeOffset($cacheKey);
141                 } // END - if
142
143                 // Handle it over to the middleware
144                 FrameworkBootstrap::getDatabaseInstance()->queryUpdateDataSet($dataSetInstance);
145         }
146
147         /**
148          * Getter for index key
149          *
150          * @return      $indexKey       Index key
151          */
152         public final function getIndexKey () {
153                 return FrameworkBootstrap::getDatabaseInstance()->getIndexKey();
154         }
155
156         /**
157          * Getter for last exception
158          *
159          * @return      $lastException  Last exception or NULL if none occured
160          */
161         public final function getLastException () {
162                 return FrameworkBootstrap::getDatabaseInstance()->getLastException();
163         }
164
165         /**
166          * Do a "select" query on the current table with the given search criteria and
167          * store it in cache for later usage
168          *
169          * @param       $criteriaInstance       An instance of a Criteria class
170          * @param       $onlyKeys                       Only use these keys for a cache key
171          * @return      $resultInstance         An instance of a database result class
172          */
173         public function doSelectByCriteria (Criteria $criteriaInstance, array $onlyKeys = array()) {
174                 // Default cache key if cache is not enabled
175                 $cacheKey = NULL;
176
177                 // Is the cache enabled?
178                 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
179                         // First get a key suitable for our cache and extend it with this class name
180                         $cacheKey = $this->getCacheKeyByCriteria($criteriaInstance, $onlyKeys);
181                 } // END - if
182
183                 // Does this key exists in cache?
184                 if (($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) && ($this->cacheInstance->offsetExists($cacheKey, BaseDatabaseBackend::RESULT_INDEX_ROWS, 1))) {
185                         // Debug message
186                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Cache used for cacheKey=' . $cacheKey . ':' . print_r($this->cacheInstance->offsetGet($cacheKey), true));
187
188                         // Then use this result
189                         $result = $this->cacheInstance->offsetGet($cacheKey);
190                 } else {
191                         // Debug message
192                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: Quering database, cacheKey=' . $cacheKey);
193
194                         // Now it's time to ask the database layer for this select statement
195                         $result = FrameworkBootstrap::getDatabaseInstance()->doSelectByTableCriteria($this->getTableName(), $criteriaInstance);
196                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: result[]=' . gettype($result));
197
198                         // Cache the result if not null
199                         if (!is_null($result)) {
200                                 // Is cache enabled?
201                                 if ($this->getConfigInstance()->getConfigEntry('database_cache_enabled') === true) {
202                                         // A valid result has returned from the database layer
203                                         $this->cacheInstance->offsetSet($cacheKey, $result);
204                                 } // END - if
205                         } else {
206                                 // This invalid result must be wrapped
207                                 $result = array(
208                                         BaseDatabaseBackend::RESULT_INDEX_STATUS    => 'invalid',
209                                         BaseDatabaseBackend::RESULT_INDEX_EXCEPTION => FrameworkBootstrap::getDatabaseInstance()->getLastException()
210                                 );
211                         }
212                 }
213
214                 // Create an instance of a CachedDatabaseResult class with the given result
215                 // @TODO Minor: Update above comment to e.g. BaseDatabaseResult
216                 $resultInstance = ObjectFactory::createObjectByConfiguredName('database_result_class', array($result));
217
218                 // And return the instance
219                 return $resultInstance;
220         }
221
222         /**
223          * Count the numbers of rows we shall receive
224          *
225          * @param       $criteriaInstance       An instance of a Criteria class
226          * @param       $onlyKeys                       Only use these keys for a cache key
227          * @return      $numRows                        Numbers of rows of database entries
228          */
229         public function doSelectCountByCriteria (Criteria $criteriaInstance, $onlyKeys = array()) {
230                 // Total numbers is -1 so we can distinglish between failed and valid queries
231                 $numRows = 0;
232
233                 // Get the result from above method
234                 $resultInstance = $this->doSelectByCriteria($criteriaInstance, $onlyKeys);
235
236                 // Was that query fine?
237                 if ($resultInstance->ifStatusIsOkay()) {
238                         // Then get the number of rows
239                         $numRows = $resultInstance->getAffectedRows();
240
241                         // Debug message
242                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-WRAPPER: numRows=' . $numRows);
243                 } // END - if
244
245                 // Return the result
246                 return $numRows;
247         }
248
249         /**
250          * Getter for primary key used in wrapped table
251          *
252          * @return      $primaryKey             Primary key used in wrapped table
253          */
254         public final function getPrimaryKeyValue () {
255                 // Get the table name and a database instance and ask for it
256                 $primaryKey = FrameworkBootstrap::getDatabaseInstance()->getPrimaryKeyOfTable($this->getTableName());
257
258                 // Return value
259                 return $primaryKey;
260         }
261
262         /**
263          * Count rows of this table
264          *
265          * @return      $count  Count of total rows in this table
266          */
267         public final function countTotalRows () {
268                 // Get the table name and a database instance and ask for it
269                 $count = FrameworkBootstrap::getDatabaseInstance()->countTotalRows($this->getTableName());
270
271                 // Return value
272                 return $count;
273         }
274
275         /**
276          * Removes non-public data from given array.
277          *
278          * @param       $data   An array with possible non-public data that needs to be removed.
279          * @return      $data   A cleaned up array with only public data.
280          */
281         public function removeNonPublicDataFromArray (array $data) {
282                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: Calling this->getDatabaseInstance()->removeNonPublicDataFromArray(data) ...');
283                 $data = FrameworkBootstrap::getDatabaseInstance()->removeNonPublicDataFromArray($data);
284
285                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('WRAPPER[' . $this->__toString() . ']: data[]=' . gettype($data));
286                 return $data;
287         }
288
289 }