DBResourceBundle::initialize()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?PHP
2
3
/**
4
 * AppserverIo\Resources\DBResourceBundle
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2018 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/resources
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Resources;
22
23
use AppserverIo\Lang\String;
24
use AppserverIo\Properties\Properties;
25
use AppserverIo\Collections\ArrayList;
26
27
/**
28
 * This class is a container for the resources and provides methods for handling them.
29
 *
30
 * Properties for the database connection are:
31
 *
32
 * db.connect.dsn = sqlite:/tmp/my-database.sqlite
33
 * db.connect.user =
34
 * db.connect.password =
35
 * db.sql.table = resources
36
 * db.sql.locale.column = locale
37
 * db.sql.key.column = msgKey
38
 * db.sql.val.column = val
39
 * resource.cache = true
40
 *
41
 * @author    Tim Wagner <[email protected]>
42
 * @copyright 2018 TechDivision GmbH <[email protected]>
43
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
44
 * @link      https://github.com/appserver-io/resources
45
 * @link      http://www.appserver.io
46
 */
47
class DBResourceBundle extends AbstractResourceBundle
48
{
49
50
    /**
51
     * Holds the the DSN used to connect to the database.
52
     *
53
     * @var string
54
     */
55
    const DB_CONNECT_DSN = 'db.connect.dsn';
56
57
    /**
58
     * Holds the the name of the key with the database user to use.
59
     *
60
     * @var string
61
     */
62
    const DB_CONNECT_USER = 'db.connect.user';
63
64
    /**
65
     * Holds the the name of the key with the database password to use.
66
     *
67
     * @var string
68
     */
69
    const DB_CONNECT_PASSWORD = 'db.connect.password';
70
71
    /**
72
     * Holds the name of the database table where the properties are stored.
73
     *
74
     * @var string
75
     */
76
    const DB_SQL_TABLE = "db.sql.table";
77
78
    /**
79
     * Holds the name of the column with the locale stored.
80
     *
81
     * @var string
82
     */
83
    const DB_SQL_LOCALE_COLUMN = "db.sql.locale.column";
84
85
    /**
86
     * Holds the name of the column with the key stored.
87
     *
88
     * @var string
89
     */
90
    const DB_SQL_KEY_COLUMN = "db.sql.key.column";
91
92
    /**
93
     * Holds the name of the column with the value stored.
94
     *
95
     * @var string
96
     */
97
    const DB_SQL_VAL_COLUMN = "db.sql.val.column";
98
99
    /**
100
     * Holds the cache flag to cache the alread loaded properties.
101
     *
102
     * @var string
103
     */
104
    const RESOURCE_CACHE = "resource.cache";
105
106
    /**
107
     * Holds the Properties necessary to initialize the database connection.
108
     *
109
     * @var Properties
110
     */
111
    protected $properties = null;
112
113
    /**
114
     * Holds the database connection to request the resources from.
115
     *
116
     * @var \PDO
117
     */
118
    protected $db = null;
119
120
    /**
121
     * Holds the flag that resources should be cached or not.
122
     *
123
     * @var boolean
124
     */
125
    protected $cacheResources = true;
126
127
    /**
128
     * Holds the path to the database configuration file.
129
     *
130
     * @var \AppserverIo\Lang\String
131
     */
132
    protected $config = null;
133
134
    /**
135
     * Initializes the resource bundle with the configuration and the locale to use.
136
     *
137
     * @param \AppserverIo\Lang\String            $config       The configuration for the database connection
138
     * @param \AppserverIo\Resources\SystemLocale $systemLocale The system locale to use
139
     *
140
     * @return void
141
     */
142
    protected function __construct(String $config, SystemLocale $systemLocale)
143
    {
144
        parent::__construct($systemLocale);
145
        $this->config = $config;
0 ignored issues
show
Documentation Bug introduced by
It seems like $config of type string is incompatible with the declared type AppserverIo\Lang\String of property $config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
146
    }
147
148
    /**
149
     * This method initializes the property resource bundle for the propertees with the
150
     * passed configuration file name and locale.
151
     *
152
     * @param \AppserverIo\Lang\String            $config       Holds the name of the property file to load the configuration from
153
     * @param \AppserverIo\Resources\SystemLocale $systemLocale Holds the system locale of the property resource bundle to load
154
     *
155
     * @return \AppserverIo\Resources\PropertyResourceBundle Holds the initialized property resource bundle
156
     */
157
    public static function getBundle(String $config, SystemLocale $systemLocale = null)
158
    {
159
160
        // use the default system locale if no locale has been passed
161
        if ($systemLocale == null) {
162
            $systemLocale = SystemLocale::getDefault();
163
        }
164
165
        // initialize and return the resource bundle
166
        $bundle = new DBResourceBundle($config, $systemLocale);
167
        $bundle->initialize();
168
        return $bundle;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $bundle returns the type AppserverIo\Resources\DBResourceBundle which is incompatible with the documented return type AppserverIo\Resources\PropertyResourceBundle.
Loading history...
169
    }
170
171
    /**
172
     *
173
     * /**
174
     * This method initializes the database connection
175
     * and returns id.
176
     *
177
     * @return \PDO Holds the initialized database connection
178
     * @throws \AppserverIo\Resources\Exceptions\ResourcesException Is thrown if an error while conneting to the database occurs
179
     */
180
    public function initialize()
181
    {
182
183
        // load the properties
184
        $this->properties = new Properties();
185
        $this->properties->load($this->config . ".properties");
0 ignored issues
show
Bug introduced by
$this->config . '.properties' of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $file of AppserverIo\Properties\Properties::load(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

185
        $this->properties->load(/** @scrutinizer ignore-type */ $this->config . ".properties");
Loading history...
186
187
        // initialize the flag to cache the resources
188
        $this->cacheResources = (boolean) $this->properties->getProperty(DBResourceBundle::RESOURCE_CACHE);
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...eBundle::RESOURCE_CACHE of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

188
        $this->cacheResources = (boolean) $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::RESOURCE_CACHE);
Loading history...
189
190
        // initialize the database connection
191
        $this->db = new \PDO(
192
            $this->properties->getProperty(DBResourceBundle::DB_CONNECT_DSN),
193
            $this->properties->getProperty(DBResourceBundle::DB_CONNECT_USER),
194
            $this->properties->getProperty(DBResourceBundle::DB_CONNECT_PASSWORD)
195
        );
196
197
        // we want exceptions if connection can not be established
198
        $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
199
    }
200
201
    /**
202
     * This method disconnects from the database and frees the memory.
203
     *
204
     * @return void
205
     */
206
    public function destroy()
207
    {
208
        $this->db = null;
209
    }
210
211
    /**
212
     * This method searches in the container for the resource with the key passed as parameter.
213
     *
214
     * @param string                             $name      Holds the key of the requested resource
215
     * @param \AppserverIo\Collections\ArrayList $parameter Holds an ArrayList with parameters with replacements for the placeholders in the resource string
216
     *
217
     * @return string Holds the requested resource value
218
     */
219
    public function find($name, ArrayList $parameter = null)
220
    {
221
222
        // initialize an find the resource string
223
        $resource = "";
224
225
        // initialize the SQL statement
226
        $stmt = sprintf(
227
            "SELECT `%s` FROM `%s` WHERE `%s` = ? AND `%s` = ?",
228
            $this->properties->getProperty(DBResourceBundle::DB_SQL_VAL_COLUMN),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...ndle::DB_SQL_VAL_COLUMN of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

228
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_VAL_COLUMN),
Loading history...
229
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
230
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN),
231
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN)
232
        );
233
234
        // prepare and execute the statement to load the requested resource string from the database
235
        $statement = $this->db->prepare($stmt);
236
237
        // get the result with the values
238
        $statement->execute(array($name, $this->getSystemLocale()->__toString()));
239
240
        // load the found row
241
        while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
242
            $resource = $row[$this->properties->getProperty(DBResourceBundle::DB_SQL_VAL_COLUMN)];
243
        }
244
245
        // check if parameter for replacement are passed
246
        if ($parameter != null) {
247
            // replace the placeholders with the passed parameter
248
            foreach ($parameter as $key => $value) {
249
                $resource = str_replace($key . "?", $value, $resource);
250
            }
251
        }
252
253
        // return the resource string
254
        return $resource;
255
    }
256
257
    /**
258
     * This method replaces the resource string with the passed key in the resource file.
259
     *
260
     * If the resource string does not yes exist, the value will be attached
261
     *
262
     * @param string $name  Holds the name of the resource string to replace
263
     * @param string $value Holds the value to replace the original one with
264
     *
265
     * @return void
266
     */
267
    public function replace($name, $value)
268
    {
269
270
        // initialize the SQL statement
271
        $stmt = sprintf(
272
            "UPDATE `%s` SET `%s` = ?, `%s` = ? WHERE `%s` = ?",
273
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...rceBundle::DB_SQL_TABLE of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

273
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_TABLE),
Loading history...
274
            $this->properties->getProperty(DBResourceBundle::DB_SQL_VAL_COLUMN),
275
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN),
276
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN)
277
        );
278
279
        // prepare and execute the statement to load the keys
280
        $statement = $this->db->prepare($stmt);
281
282
        // replace the value for the resource with the passed name
283
        $statement->execute(array($value, $this->getSystemLocale()->__toString(), $name));
284
    }
285
286
    /**
287
     * This method attaches the resource string with the passed key in the resource file.
288
     *
289
     * If the resource string already exists, the old one will be kept and the function
290
     * returns FALSE, else it returns TRUE
291
     *
292
     * @param string $name  Holds the name of the resource string to replace
293
     * @param string $value Holds the value to replace the original one with
294
     *
295
     * @return void
296
     */
297
    public function attach($name, $value)
298
    {
299
300
        // initialize the SQL statement
301
        $stmt = sprintf(
302
            "INSERT INTO `%s` (`%s`, `%s`, `%s`) VALUES (?, ?, ?)",
303
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...rceBundle::DB_SQL_TABLE of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

303
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_TABLE),
Loading history...
304
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN),
305
            $this->properties->getProperty(DBResourceBundle::DB_SQL_VAL_COLUMN),
306
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN)
307
        );
308
309
        // prepare and execute the statement to attach the resources
310
        $statement = $this->db->prepare($stmt);
311
312
        // try to excecute the statement
313
        $statement->execute(array($name, $value, $this->getSystemLocale()->__toString()));
314
    }
315
316
    /**
317
     * This method returns the first key found for the passed value.
318
     *
319
     * @param string $value Holds the resource value to return the key for
320
     *
321
     * @return string Holds the resource key for the passed value
322
     */
323
    public function findKeyByValue($value)
324
    {
325
326
        // initialize the SQL statement
327
        $stmt = sprintf(
328
            "SELECT `%s` FROM `%s` WHERE `%s` = ? AND `%s` = ?",
329
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...ndle::DB_SQL_KEY_COLUMN of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

329
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_KEY_COLUMN),
Loading history...
330
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
331
            $this->properties->getProperty(DBResourceBundle::DB_SQL_VAL_COLUMN),
332
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN)
333
        );
334
335
        // prepare the statement to load the requested resource key from the database
336
        $statement = $this->db->prepare($stmt);
337
338
        // execute the statement
339
        $statement->execute(array($value, $this->getSystemLocale()->__toString()));
340
341
        // iterate over the result
342
        while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
343
            $resource = $row[$this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN)];
344
        }
345
346
        // return the resource string
347
        return $resource;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $resource does not seem to be defined for all execution paths leading up to this point.
Loading history...
348
    }
349
350
    /**
351
     * This method returns the number of resources in the container.
352
     *
353
     * @return integer Number of resources in the container
354
     */
355
    public function count()
356
    {
357
358
        // initialize the SQL statement
359
        $stmt = sprintf(
360
            "SELECT COUNT(`%s`) AS size FROM `%s` WHERE `%s` = ? GROUP BY `%s`",
361
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...ndle::DB_SQL_KEY_COLUMN of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

361
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_KEY_COLUMN),
Loading history...
362
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
363
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN),
364
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN)
365
        );
366
367
        // prepare the statement
368
        $statement = $this->db->prepare($stmt);
369
370
        // execute the statement count the resources
371
        $statement->execute(array($this->getSystemLocale()->__toString()));
372
373
        // return the size of the found resources
374
        while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
375
            return $row["size"];
376
        }
377
    }
378
379
    /**
380
     * This method saves all resources back to
381
     * the database.
382
     *
383
     * @return void
384
     */
385
    public function save()
386
    {
387
        // Nothing to do here, because all values are saved immediately
388
    }
389
390
    /**
391
     * Returns the keys of this ResourceBundle instance as an ArrayList.
392
     *
393
     * @return \AppserverIo\Collections\ArrayList Holds the keys of this ResourceBundle instance
394
     */
395
    public function getKeys()
396
    {
397
398
        // initialize the ArrayList with the keys
399
        $list = new ArrayList();
400
401
        // initialize the SQL statement
402
        $stmt = sprintf(
403
            "SELECT `%s` FROM `%s` WHERE `%s` = ? GROUP BY `%s`",
404
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN),
0 ignored issues
show
Bug introduced by
AppserverIo\Resources\DB...ndle::DB_SQL_KEY_COLUMN of type string is incompatible with the type AppserverIo\Lang\String expected by parameter $key of AppserverIo\Properties\Properties::getProperty(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

404
            $this->properties->getProperty(/** @scrutinizer ignore-type */ DBResourceBundle::DB_SQL_KEY_COLUMN),
Loading history...
405
            $this->properties->getProperty(DBResourceBundle::DB_SQL_TABLE),
406
            $this->properties->getProperty(DBResourceBundle::DB_SQL_LOCALE_COLUMN),
407
            $this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN)
408
        );
409
410
        // prepare the statement to load the keys
411
        $statement = $this->db->prepare($stmt);
412
413
        // execute the statement
414
        $statement->execute(array($this->getSystemLocale()->__toString()));
415
416
        // build the ArrayList
417
        while ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
418
            $list->add($row[$this->properties->getProperty(DBResourceBundle::DB_SQL_KEY_COLUMN)]);
419
        }
420
421
        // return the ArrayList with the keys
422
        return $list;
423
    }
424
}
425