1 | <?php |
||||||
2 | |||||||
3 | /** |
||||||
4 | * TDbParameterModule class |
||||||
5 | * |
||||||
6 | * @author Brad Anderson <[email protected]> |
||||||
7 | * @link https://github.com/pradosoft/prado |
||||||
8 | * @license https://github.com/pradosoft/prado/blob/master/LICENSE |
||||||
9 | */ |
||||||
10 | |||||||
11 | namespace Prado\Util; |
||||||
12 | |||||||
13 | use Exception; |
||||||
14 | use PDO; |
||||||
15 | use Prado\Data\TDataSourceConfig; |
||||||
16 | use Prado\Data\TDbConnection; |
||||||
17 | use Prado\Exceptions\TConfigurationException; |
||||||
18 | use Prado\Exceptions\TInvalidDataTypeException; |
||||||
19 | use Prado\Exceptions\TInvalidOperationException; |
||||||
20 | use Prado\TModule; |
||||||
21 | use Prado\TPropertyValue; |
||||||
22 | use Prado\Security\Permissions\IPermissions; |
||||||
23 | use Prado\Security\Permissions\TPermissionEvent; |
||||||
24 | use Prado\Util\Behaviors\TMapLazyLoadBehavior; |
||||||
25 | use Prado\Util\Behaviors\TMapRouteBehavior; |
||||||
26 | |||||||
27 | /** |
||||||
28 | * TDbParameterModule class |
||||||
29 | * |
||||||
30 | * This loads application parameters from a database. It adds the |
||||||
31 | * {@see \Prado\Util\Behaviors\TMapLazyLoadBehavior} to Application Parameters when the |
||||||
32 | * {@see setAutoLoadField} is set. The key and name fields, table, |
||||||
33 | * autoload field, and autoload values (both true and false values) |
||||||
34 | * are parameterized. Set them to your application specific values. |
||||||
35 | * |
||||||
36 | * The following will load the options from a WordPress Database: |
||||||
37 | * ```xml |
||||||
38 | * <module id="dbparams" class="Prado\Util\TDbParameterModule" |
||||||
39 | * ConnectionID="DB" KeyField="option_name" ValueField="option_value" TableName="wp_options" Serializer="php" |
||||||
40 | * autoLoadField="autoload" autoLoadValue="'yes'" autoLoadValueFalse="'no'"/> |
||||||
41 | * ``` |
||||||
42 | * |
||||||
43 | * This allows for setting and removal of application parameters |
||||||
44 | * into and from the database through {@see set} and |
||||||
45 | * {@see remove}, respectively. Arrays and Objects are |
||||||
46 | * serialized. The specific serializer can be chose to be 'php', |
||||||
47 | * 'json', or provide your own function or callable. Default to 'php'. |
||||||
48 | * |
||||||
49 | * setting {@see setSerializer} to your own function that has the |
||||||
50 | * following format: |
||||||
51 | * ```php |
||||||
52 | * function mySerializerFunction($data, $encode) {...} |
||||||
53 | * ``` |
||||||
54 | * If $encode is true, then encode, otherwise decode, to text. |
||||||
55 | * |
||||||
56 | * When {@see getCaptureParameterChanges} is true, the default, |
||||||
57 | * then this will route any changes to the Application Parameters |
||||||
58 | * after TPageService::onPreRunPage back to the TDbParameterModule |
||||||
59 | * and be saved to the database. This captures any changes when |
||||||
60 | * done by the page or user. These changes are restored when |
||||||
61 | * this module is loaded again. |
||||||
62 | * |
||||||
63 | * When TPermissionsManager is a module in your app, there is one permission |
||||||
64 | * to control user access to its function: |
||||||
65 | * - TDbParameterModule::PERM_PARAM_SHELL 'param_shell' enables the shell command to index, get and set database parameters. |
||||||
66 | * |
||||||
67 | * The role and rule management functions only work when the TDbParameter Module is specified. |
||||||
68 | * The following gives user "admin" and all users with "Administrators" role the |
||||||
69 | * permission to access permissions shell and its full functionality: |
||||||
70 | * ```xml |
||||||
71 | * <permissionrule name="param_shell" action="allow" users="admin" /> |
||||||
72 | * <permissionrule name="param_shell" action="allow" roles="Administrators" /> |
||||||
73 | * ``` |
||||||
74 | * |
||||||
75 | * @author Brad Anderson <[email protected]> |
||||||
76 | * @since 4.2.0 |
||||||
77 | * @method bool dyRegisterShellAction($returnValue) |
||||||
78 | */ |
||||||
79 | class TDbParameterModule extends TModule implements IDbModule, IPermissions |
||||||
80 | { |
||||||
81 | public const SERIALIZE_PHP = 'php'; |
||||||
82 | |||||||
83 | public const SERIALIZE_JSON = 'json'; |
||||||
84 | |||||||
85 | /** The permission for the cron shell */ |
||||||
86 | public const PERM_PARAM_SHELL = 'param_shell'; |
||||||
87 | |||||||
88 | /** |
||||||
89 | * The name of the Application Parameter Lazy Load Behavior |
||||||
90 | */ |
||||||
91 | public const APP_PARAMETER_LAZY_BEHAVIOR = 'lazyTDbParameter'; |
||||||
92 | |||||||
93 | /** |
||||||
94 | * The name of the Application Parameter Lazy Load Behavior |
||||||
95 | */ |
||||||
96 | public const APP_PARAMETER_SET_BEHAVIOR = 'setTDbParameter'; |
||||||
97 | |||||||
98 | /** |
||||||
99 | * @var string the ID of TDataSourceConfig module |
||||||
100 | */ |
||||||
101 | private $_connID = ''; |
||||||
102 | |||||||
103 | /** |
||||||
104 | * @var TDbConnection the DB connection instance |
||||||
105 | */ |
||||||
106 | private $_conn; |
||||||
107 | |||||||
108 | /** |
||||||
109 | * @var bool whether or not the database parameters have been loaded. |
||||||
110 | * when true none of the variables can be changed |
||||||
111 | */ |
||||||
112 | private $_initialized = false; |
||||||
113 | |||||||
114 | /** |
||||||
115 | * @var string The key field for the parameter from the database |
||||||
116 | */ |
||||||
117 | private $_keyField = 'param_key'; |
||||||
118 | |||||||
119 | /** |
||||||
120 | * @var string The value field for the parameter from the database |
||||||
121 | */ |
||||||
122 | private $_valueField = 'param_value'; |
||||||
123 | |||||||
124 | /** |
||||||
125 | * @var string The table name for the parameters from the database |
||||||
126 | */ |
||||||
127 | private $_tableName = 'parameters'; |
||||||
128 | |||||||
129 | /** |
||||||
130 | * @var string autoload Field. default "", meaning no autoload field |
||||||
131 | */ |
||||||
132 | private $_autoLoadField = 'autoload'; |
||||||
133 | |||||||
134 | /** |
||||||
135 | * @var string autoload True value. default sql "1" |
||||||
136 | */ |
||||||
137 | private $_autoLoadValue = '1'; |
||||||
138 | |||||||
139 | /** |
||||||
140 | * @var string autoload False value. default sql "0" |
||||||
141 | */ |
||||||
142 | private $_autoLoadValueFalse = '0'; |
||||||
143 | |||||||
144 | /** |
||||||
145 | * @var bool whether the parameter DB table should be created automatically |
||||||
146 | */ |
||||||
147 | private $_autoCreate = true; |
||||||
148 | |||||||
149 | /** |
||||||
150 | * @var bool whether ensureTable was called |
||||||
151 | */ |
||||||
152 | private $_tableEnsured; |
||||||
153 | |||||||
154 | /** |
||||||
155 | * @var callable|string which serialize function to use, |
||||||
156 | */ |
||||||
157 | private $_serializer = self::SERIALIZE_PHP; |
||||||
158 | |||||||
159 | /** |
||||||
160 | * @var bool automatically capture changes to Parameters after Application Initialize |
||||||
161 | */ |
||||||
162 | private $_autoCapture = true; |
||||||
163 | |||||||
164 | /** |
||||||
165 | * @var TMapRouteBehavior captures all the changes to the parameters to the db |
||||||
166 | */ |
||||||
167 | private $_setBehavior; |
||||||
168 | |||||||
169 | /** |
||||||
170 | * Initializes the module by loading parameters. |
||||||
171 | * @param mixed $config content enclosed within the module tag |
||||||
172 | */ |
||||||
173 | public function init($config) |
||||||
174 | { |
||||||
175 | $this->loadDbParameters(); |
||||||
176 | $this->_initialized = true; |
||||||
177 | |||||||
178 | if ($this->_autoLoadField) { |
||||||
179 | $this->getApplication()->getParameters()->attachBehavior(self::APP_PARAMETER_LAZY_BEHAVIOR, new TMapLazyLoadBehavior([$this, 'getFromBehavior'])); |
||||||
180 | } |
||||||
181 | if ($this->_autoCapture) { |
||||||
182 | $this->getApplication()->attachEventHandler('onBeginRequest', [$this, 'attachTPageServiceHandler']); |
||||||
183 | } |
||||||
184 | $app = $this->getApplication(); |
||||||
185 | $app->attachEventHandler('onAuthenticationComplete', [$this, 'registerShellAction']); |
||||||
186 | parent::init($config); |
||||||
187 | } |
||||||
188 | |||||||
189 | /** |
||||||
190 | * @param \Prado\Security\Permissions\TPermissionsManager $manager |
||||||
191 | * @return \Prado\Security\Permissions\TPermissionEvent[] |
||||||
192 | */ |
||||||
193 | public function getPermissions($manager) |
||||||
194 | { |
||||||
195 | return [ |
||||||
196 | new TPermissionEvent(static::PERM_PARAM_SHELL, 'Activates parameter shell commands.', 'dyRegisterShellAction'), |
||||||
197 | ]; |
||||||
198 | } |
||||||
199 | |||||||
200 | /** |
||||||
201 | * Loads parameters from the database into the application. |
||||||
202 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
203 | */ |
||||||
204 | protected function loadDbParameters() |
||||||
205 | { |
||||||
206 | $db = $this->getDbConnection(); |
||||||
207 | |||||||
208 | $this->ensureTable(); |
||||||
209 | |||||||
210 | $where = ($this->_autoLoadField ? " WHERE {$this->_autoLoadField}={$this->_autoLoadValue}" : ''); |
||||||
211 | $cmd = $db->createCommand( |
||||||
212 | "SELECT {$this->_keyField} as keyField, {$this->_valueField} as valueField FROM {$this->_tableName}{$where}" |
||||||
213 | ); |
||||||
214 | $results = $cmd->query(); |
||||||
215 | |||||||
216 | $appParameters = $this->getApplication()->getParameters(); |
||||||
217 | $serializer = $this->getSerializer(); |
||||||
218 | foreach ($results->readAll() as $row) { |
||||||
219 | $value = $row['valueField']; |
||||||
220 | if ($serializer == self::SERIALIZE_PHP) { |
||||||
221 | if (($avalue = @unserialize($value)) !== false) { |
||||||
222 | $value = $avalue; |
||||||
223 | } |
||||||
224 | } elseif ($serializer == self::SERIALIZE_JSON) { |
||||||
225 | if (($avalue = json_decode($value, true)) !== null) { |
||||||
226 | $value = $avalue; |
||||||
227 | } |
||||||
228 | } elseif ($serializer) { |
||||||
229 | if (($avalue = call_user_func($serializer, $value, false)) !== null) { |
||||||
230 | $value = $avalue; |
||||||
231 | } |
||||||
232 | } |
||||||
233 | $appParameters[$row['keyField']] = $value; |
||||||
234 | } |
||||||
235 | } |
||||||
236 | |||||||
237 | /** |
||||||
238 | * TApplication::onBeginRequest Handler that adds {@see attachTPageBehaviors} to |
||||||
239 | * TPageService::onPreRunPage. In turn, this attaches {@see attachTPageBehaviors} |
||||||
240 | * to TPageService to then adds the page behaviors. |
||||||
241 | * @param object $sender the object that raised the event |
||||||
242 | * @param mixed $param parameter of the event |
||||||
243 | */ |
||||||
244 | public function attachTPageServiceHandler($sender, $param) |
||||||
0 ignored issues
–
show
The parameter
$param is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
245 | { |
||||||
246 | $service = $this->getService(); |
||||||
247 | if ($service->hasEvent('onPreRunPage')) { |
||||||
248 | $service->attachEventHandler('onPreRunPage', [$this, 'attachParameterStorage'], 0); |
||||||
0 ignored issues
–
show
0 of type integer is incompatible with the type Prado\numeric|null expected by parameter $priority of Prado\TComponent::attachEventHandler() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
249 | } |
||||||
250 | } |
||||||
251 | |||||||
252 | /** |
||||||
253 | * @param object $sender sender of this event handler |
||||||
254 | * @param null|mixed $param parameter for the event |
||||||
255 | */ |
||||||
256 | public function registerShellAction($sender, $param) |
||||||
0 ignored issues
–
show
The parameter
$param is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$sender is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
257 | { |
||||||
258 | if ($this->dyRegisterShellAction(false) !== true && ($app = $this->getApplication()) instanceof \Prado\Shell\TShellApplication) { |
||||||
259 | $app->addShellActionClass(['class' => \Prado\Shell\Actions\TDbParameterAction::class, 'DbParameterModule' => $this]); |
||||||
0 ignored issues
–
show
array('class' => Prado\S...ameterModule' => $this) of type array<string,Prado\Util\...ParameterModule|string> is incompatible with the type string expected by parameter $class of Prado\Shell\TShellApplic...::addShellActionClass() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
260 | } |
||||||
261 | } |
||||||
262 | |||||||
263 | /** |
||||||
264 | * This attaches the TMapRouteBehavior on the Parameters. |
||||||
265 | * @param object $sender |
||||||
266 | * @param null|mixed $param |
||||||
267 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
268 | */ |
||||||
269 | public function attachParameterStorage($sender, $param) |
||||||
0 ignored issues
–
show
The parameter
$param is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() The parameter
$sender is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
270 | { |
||||||
271 | $this->_setBehavior = new TMapRouteBehavior(null, [$this, 'setFromBehavior']); |
||||||
272 | $this->getApplication()->getParameters()->attachBehavior(self::APP_PARAMETER_SET_BEHAVIOR, $this->_setBehavior); |
||||||
273 | } |
||||||
274 | |||||||
275 | /** |
||||||
276 | * Creates the DB table for storing log messages. |
||||||
277 | * @todo create sequence for PostgreSQL, and other db |
||||||
278 | */ |
||||||
279 | protected function createDbTable() |
||||||
280 | { |
||||||
281 | $db = $this->getDbConnection(); |
||||||
282 | $driver = $db->getDriverName(); |
||||||
283 | $autoidAttributes = ''; |
||||||
284 | $autotype = 'INTEGER'; |
||||||
285 | $postIndices = '; CREATE UNIQUE INDEX tkey ON ' . $this->_tableName . '(' . $this->_keyField . ');' . |
||||||
286 | ($this->_autoLoadField ? ' CREATE INDEX tauto ON ' . $this->_tableName . '(' . $this->_autoLoadField . ');' : ''); |
||||||
287 | |||||||
288 | switch ($driver) { |
||||||
289 | case 'sqlite': |
||||||
290 | $autoidAttributes = ' AUTOINCREMENT'; |
||||||
291 | break; |
||||||
292 | case 'postgresql': |
||||||
293 | $autotype = 'SERIAL'; |
||||||
294 | break; |
||||||
295 | default: // mysql |
||||||
296 | $autoidAttributes = ' AUTO_INCREMENT'; |
||||||
297 | break; |
||||||
298 | } |
||||||
299 | |||||||
300 | $sql = 'CREATE TABLE ' . $this->_tableName . ' ( |
||||||
301 | param_id ' . $autotype . ' PRIMARY KEY ' . $autoidAttributes . ', ' . |
||||||
302 | $this->_keyField . ' VARCHAR(128) NOT NULL,' . |
||||||
303 | $this->_valueField . ' MEDIUMTEXT' . |
||||||
304 | ($this->_autoLoadField ? ', ' . $this->_autoLoadField . ' BOOLEAN NOT NULL DEFAULT 1' : '') . |
||||||
305 | ')' . $postIndices; |
||||||
306 | $db->createCommand($sql)->execute(); |
||||||
307 | } |
||||||
308 | |||||||
309 | /** |
||||||
310 | * checks for the table, and if not there and autoCreate, then creates the table else throw error. |
||||||
311 | * @throws \Prado\Exceptions\TConfigurationException if the table does not exist and cannot autoCreate |
||||||
312 | */ |
||||||
313 | protected function ensureTable() |
||||||
314 | { |
||||||
315 | if ($this->_tableEnsured) { |
||||||
316 | return; |
||||||
317 | } |
||||||
318 | $this->_tableEnsured = true; |
||||||
319 | $db = $this->getDbConnection(); |
||||||
320 | $sql = 'SELECT * FROM ' . $this->_tableName . ' WHERE 0=1'; |
||||||
321 | try { |
||||||
322 | $db->createCommand($sql)->query()->close(); |
||||||
323 | } catch (Exception $e) { |
||||||
324 | // DB table not exists |
||||||
325 | if ($this->_autoCreate) { |
||||||
326 | $this->createDbTable(); |
||||||
327 | } else { |
||||||
328 | throw new TConfigurationException('dbparametermodule_table_nonexistent', $this->_tableName); |
||||||
329 | } |
||||||
330 | } |
||||||
331 | } |
||||||
332 | |||||||
333 | |||||||
334 | /** |
||||||
335 | * Gets a specific parameter parameters into application. |
||||||
336 | * @param string $key key to get the value |
||||||
337 | * @param bool $checkParameter checks the Application Parameters first |
||||||
338 | * @param bool $setParameter should the method set the application parameters |
||||||
339 | * @throws \Prado\Exceptions\TInvalidOperationException if the $key is blank |
||||||
340 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
341 | * @return mixed the value of the key |
||||||
342 | */ |
||||||
343 | public function get($key, $checkParameter = true, $setParameter = true) |
||||||
344 | { |
||||||
345 | if ($key == '') { |
||||||
346 | throw new TInvalidOperationException('dbparametermodule_get_no_blank_key'); |
||||||
347 | } |
||||||
348 | |||||||
349 | if ($checkParameter) { |
||||||
350 | $appParams = $this->getApplication()->getParameters(); |
||||||
351 | if (isset($appParams[$key])) { |
||||||
352 | return $appParams[$key]; |
||||||
353 | } |
||||||
354 | } |
||||||
355 | $this->ensureTable(); |
||||||
356 | |||||||
357 | $db = $this->getDbConnection(); |
||||||
358 | $cmd = $db->createCommand( |
||||||
359 | "SELECT {$this->_valueField} as valueField FROM {$this->_tableName} WHERE {$this->_keyField}=:key LIMIT 1" |
||||||
360 | ); |
||||||
361 | $cmd->bindParameter(":key", $key, PDO::PARAM_STR); |
||||||
362 | $results = $cmd->queryRow(); |
||||||
363 | $serializer = $this->getSerializer(); |
||||||
364 | if (is_array($results) && ($value = $results['valueField']) !== null) { |
||||||
365 | if ($serializer == self::SERIALIZE_PHP) { |
||||||
366 | if (($avalue = @unserialize($value)) !== false) { |
||||||
367 | $value = $avalue; |
||||||
368 | } |
||||||
369 | } elseif ($serializer == self::SERIALIZE_JSON) { |
||||||
370 | if (($avalue = json_decode($value, true)) !== null) { |
||||||
371 | $value = $avalue; |
||||||
372 | } |
||||||
373 | } elseif ($serializer && ($avalue = call_user_func($serializer, $value, false)) !== null) { |
||||||
374 | $value = $avalue; |
||||||
375 | } |
||||||
376 | if ($setParameter) { |
||||||
377 | $appParams = $this->getApplication()->getParameters(); |
||||||
378 | $appParams[$key] = $value; |
||||||
379 | } |
||||||
380 | return $value; |
||||||
381 | } |
||||||
382 | return null; |
||||||
383 | } |
||||||
384 | |||||||
385 | /** |
||||||
386 | * Loads parameters into application. |
||||||
387 | * @param string $key key to get the value |
||||||
388 | * @throws \Prado\Exceptions\TInvalidOperationException if the $key is blank |
||||||
389 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
390 | * @return mixed the value |
||||||
391 | */ |
||||||
392 | public function getFromBehavior($key) |
||||||
393 | { |
||||||
394 | return $this->get($key, false, $this->_setBehavior === null); |
||||||
395 | } |
||||||
396 | |||||||
397 | /** |
||||||
398 | * Sets a parameter in the database and the Application Parameter. |
||||||
399 | * @param string $key the key of the parameter |
||||||
400 | * @param mixed $value the key of the parameter |
||||||
401 | * @param bool $autoLoad should the key be autoloaded at init |
||||||
402 | * @param mixed $setParameter |
||||||
403 | * @throws \Prado\Exceptions\TInvalidOperationException if the $key is blank |
||||||
404 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
405 | */ |
||||||
406 | public function set($key, $value, $autoLoad = true, $setParameter = true) |
||||||
407 | { |
||||||
408 | if (empty($key)) { |
||||||
409 | throw new TInvalidOperationException('dbparametermodule_set_no_blank_key'); |
||||||
410 | } |
||||||
411 | |||||||
412 | $_value = $value; |
||||||
413 | if (($serializer = $this->getSerializer()) && (is_array($value) || is_object($value))) { |
||||||
414 | if ($serializer == self::SERIALIZE_PHP) { |
||||||
415 | $_value = @serialize($value); |
||||||
416 | } elseif ($serializer == self::SERIALIZE_JSON) { |
||||||
417 | $_value = json_encode($value, JSON_UNESCAPED_UNICODE); |
||||||
418 | } else { |
||||||
419 | $_value = call_user_func($serializer, $value, true); |
||||||
420 | } |
||||||
421 | } |
||||||
422 | $this->ensureTable(); |
||||||
423 | $db = $this->getDbConnection(); |
||||||
424 | $driver = $db->getDriverName(); |
||||||
425 | $appendix = ''; |
||||||
426 | if ($driver === 'mysql') { |
||||||
427 | $dupl = ($this->_autoLoadField ? ", {$this->_autoLoadField}=values({$this->_autoLoadField})" : ''); |
||||||
428 | $appendix = " ON DUPLICATE KEY UPDATE {$this->_valueField}=values({$this->_valueField}){$dupl}"; |
||||||
429 | } else { |
||||||
430 | $this->remove($key); |
||||||
431 | } |
||||||
432 | $field = ($this->_autoLoadField ? ", {$this->_autoLoadField}" : ''); |
||||||
433 | $values = ($this->_autoLoadField ? ", :auto" : ''); |
||||||
434 | $cmd = $db->createCommand("INSERT INTO {$this->_tableName} ({$this->_keyField}, {$this->_valueField}{$field}) " . |
||||||
435 | "VALUES (:key, :value{$values})" . $appendix); |
||||||
436 | $cmd->bindParameter(":key", $key, PDO::PARAM_STR); |
||||||
437 | $cmd->bindParameter(":value", $_value, PDO::PARAM_STR); |
||||||
438 | if ($this->_autoLoadField) { |
||||||
439 | $alv = $autoLoad ? $this->_autoLoadValue : $this->_autoLoadValueFalse; |
||||||
440 | $cmd->bindParameter(":auto", $alv, PDO::PARAM_STR); |
||||||
441 | } |
||||||
442 | $cmd->execute(); |
||||||
443 | |||||||
444 | if ($setParameter) { |
||||||
445 | $appParameters = $this->getApplication()->getParameters(); |
||||||
446 | $appParameters[$key] = $value; |
||||||
447 | } |
||||||
448 | } |
||||||
449 | |||||||
450 | /** |
||||||
451 | * Sets a parameter in the database and the Application Parameter. |
||||||
452 | * from changes to the Parameter through a TMapRouteBehavior. |
||||||
453 | * @param string $key the key of the parameter |
||||||
454 | * @param mixed $value the key of the parameter |
||||||
455 | * @throws \Prado\Exceptions\TInvalidOperationException if the $key is blank |
||||||
456 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
457 | */ |
||||||
458 | public function setFromBehavior($key, $value) |
||||||
459 | { |
||||||
460 | if ($value !== null) { |
||||||
461 | $this->set($key, $value, true, false); |
||||||
462 | } else { |
||||||
463 | $this->remove($key); |
||||||
464 | } |
||||||
465 | } |
||||||
466 | |||||||
467 | /** |
||||||
468 | * exists checks for a parameter in the database |
||||||
469 | * @param string $key parameter to check in the database |
||||||
470 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
471 | * @return bool whether the key exists in the database table |
||||||
472 | * @return mixed the value of the parameter, one last time |
||||||
473 | */ |
||||||
474 | public function exists($key) |
||||||
475 | { |
||||||
476 | $this->ensureTable(); |
||||||
477 | |||||||
478 | $db = $this->getDbConnection(); |
||||||
479 | $cmd = $db->createCommand( |
||||||
480 | "SELECT COUNT(*) AS count FROM {$this->_tableName} WHERE {$this->_keyField}=:key" |
||||||
481 | ); |
||||||
482 | $cmd->bindParameter(":key", $key, PDO::PARAM_STR); |
||||||
483 | $result = $cmd->queryRow(); |
||||||
484 | return $result['count'] > 0; |
||||||
485 | } |
||||||
486 | |||||||
487 | /** |
||||||
488 | * remove removes a parameter from the database |
||||||
489 | * @param string $key parameter to remove from the database |
||||||
490 | * @throws \Prado\Exceptions\TDbException if the Fields and table is not correct |
||||||
491 | * @return mixed the value of the key removed |
||||||
492 | * @return mixed the value of the parameter, one last time |
||||||
493 | */ |
||||||
494 | public function remove($key) |
||||||
495 | { |
||||||
496 | $value = $this->get($key, false, false); |
||||||
497 | |||||||
498 | $this->ensureTable(); |
||||||
499 | $db = $this->getDbConnection(); |
||||||
500 | $driver = $db->getDriverName(); |
||||||
501 | $appendix = ''; |
||||||
502 | if ($driver === 'mysql') { |
||||||
503 | $appendix = ' LIMIT 1'; |
||||||
504 | } |
||||||
505 | $cmd = $db->createCommand("DELETE FROM {$this->_tableName} WHERE {$this->_keyField}=:key" . $appendix); |
||||||
506 | $cmd->bindParameter(":key", $key, PDO::PARAM_STR); |
||||||
507 | $cmd->execute(); |
||||||
508 | return $value; |
||||||
509 | } |
||||||
510 | |||||||
511 | /** |
||||||
512 | * @return string the ID of a TDataSourceConfig module. Defaults to empty string, meaning not set. |
||||||
513 | */ |
||||||
514 | public function getConnectionID() |
||||||
515 | { |
||||||
516 | return $this->_connID; |
||||||
517 | } |
||||||
518 | |||||||
519 | /** |
||||||
520 | * Sets the ID of a TDataSourceConfig module. |
||||||
521 | * The datasource module will be used to establish the DB connection |
||||||
522 | * that will be used by the user manager. |
||||||
523 | * @param string $value module ID. |
||||||
524 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
525 | */ |
||||||
526 | public function setConnectionID($value) |
||||||
527 | { |
||||||
528 | if ($this->_initialized) { |
||||||
529 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'ConnectionID'); |
||||||
530 | } |
||||||
531 | $this->_connID = $value; |
||||||
532 | } |
||||||
533 | |||||||
534 | /** |
||||||
535 | * @return TDbConnection the database connection that may be used to retrieve user data. |
||||||
536 | */ |
||||||
537 | public function getDbConnection() |
||||||
538 | { |
||||||
539 | if ($this->_conn === null) { |
||||||
540 | $this->_conn = $this->createDbConnection($this->_connID); |
||||||
541 | $this->_conn->setActive(true); |
||||||
542 | } |
||||||
543 | return $this->_conn; |
||||||
544 | } |
||||||
545 | |||||||
546 | /** |
||||||
547 | * Creates the DB connection. If no ConnectionID is set, this creates a |
||||||
548 | * sqlite3 database in the RuntimePath "sqlite3.params". If the |
||||||
549 | * {@see getAutoLoadField} is not set, the default, then the autoLoadField |
||||||
550 | * is set to "autoload" to enable the feature by default. |
||||||
551 | * @param string $connectionID the module ID for TDataSourceConfig |
||||||
552 | * @throws \Prado\Exceptions\TConfigurationException if module ID is invalid or empty |
||||||
553 | * @return TDbConnection the created DB connection |
||||||
554 | */ |
||||||
555 | protected function createDbConnection($connectionID) |
||||||
556 | { |
||||||
557 | if ($connectionID !== '') { |
||||||
558 | $conn = $this->getApplication()->getModule($connectionID); |
||||||
559 | if ($conn instanceof TDataSourceConfig) { |
||||||
560 | return $conn->getDbConnection(); |
||||||
561 | } else { |
||||||
562 | throw new TConfigurationException('dbparametermodule_connectionid_invalid', $connectionID); |
||||||
563 | } |
||||||
564 | } else { |
||||||
565 | $db = new TDbConnection(); |
||||||
566 | // default to SQLite3 database |
||||||
567 | $dbFile = $this->getApplication()->getRuntimePath() . DIRECTORY_SEPARATOR . 'app.params'; |
||||||
568 | $db->setConnectionString('sqlite:' . $dbFile); |
||||||
569 | return $db; |
||||||
570 | } |
||||||
571 | } |
||||||
572 | |||||||
573 | /** |
||||||
574 | * @return string the database parameter key field |
||||||
575 | */ |
||||||
576 | public function getKeyField() |
||||||
577 | { |
||||||
578 | return $this->_keyField; |
||||||
579 | } |
||||||
580 | |||||||
581 | /** |
||||||
582 | * @param string $value database parameter key field |
||||||
583 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
584 | */ |
||||||
585 | public function setKeyField($value) |
||||||
586 | { |
||||||
587 | if ($this->_initialized) { |
||||||
588 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'KeyField'); |
||||||
589 | } |
||||||
590 | $this->_keyField = TPropertyValue::ensureString($value); |
||||||
591 | } |
||||||
592 | |||||||
593 | /** |
||||||
594 | * @return string the database parameter key value |
||||||
595 | */ |
||||||
596 | public function getValueField() |
||||||
597 | { |
||||||
598 | return $this->_valueField; |
||||||
599 | } |
||||||
600 | |||||||
601 | /** |
||||||
602 | * @param string $value database parameter key value |
||||||
603 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
604 | */ |
||||||
605 | public function setValueField($value) |
||||||
606 | { |
||||||
607 | if ($this->_initialized) { |
||||||
608 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'ValueField'); |
||||||
609 | } |
||||||
610 | $this->_valueField = TPropertyValue::ensureString($value); |
||||||
611 | } |
||||||
612 | |||||||
613 | /** |
||||||
614 | * @return string the database parameter key value |
||||||
615 | */ |
||||||
616 | public function getTableName() |
||||||
617 | { |
||||||
618 | return $this->_tableName; |
||||||
619 | } |
||||||
620 | |||||||
621 | /** |
||||||
622 | * @param string $value database parameter key value |
||||||
623 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
624 | */ |
||||||
625 | public function setTableName($value) |
||||||
626 | { |
||||||
627 | if ($this->_initialized) { |
||||||
628 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'TableName'); |
||||||
629 | } |
||||||
630 | $this->_tableName = TPropertyValue::ensureString($value); |
||||||
631 | } |
||||||
632 | |||||||
633 | /** |
||||||
634 | * @return string the database parameter key value |
||||||
635 | */ |
||||||
636 | public function getAutoLoadField() |
||||||
637 | { |
||||||
638 | return $this->_autoLoadField; |
||||||
639 | } |
||||||
640 | |||||||
641 | /** |
||||||
642 | * @param string $value database parameter key value |
||||||
643 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
644 | */ |
||||||
645 | public function setAutoLoadField($value) |
||||||
646 | { |
||||||
647 | if ($this->_initialized) { |
||||||
648 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'AutoLoadField'); |
||||||
649 | } |
||||||
650 | $this->_autoLoadField = TPropertyValue::ensureString($value); |
||||||
651 | } |
||||||
652 | |||||||
653 | /** |
||||||
654 | * @return string the database parameter key value |
||||||
655 | */ |
||||||
656 | public function getAutoLoadValue() |
||||||
657 | { |
||||||
658 | return $this->_autoLoadValue; |
||||||
659 | } |
||||||
660 | |||||||
661 | /** |
||||||
662 | * @param string $value database parameter key value |
||||||
663 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
664 | */ |
||||||
665 | public function setAutoLoadValue($value) |
||||||
666 | { |
||||||
667 | if ($this->_initialized) { |
||||||
668 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'AutoLoadValue'); |
||||||
669 | } |
||||||
670 | $this->_autoLoadValue = TPropertyValue::ensureString($value); |
||||||
671 | } |
||||||
672 | |||||||
673 | /** |
||||||
674 | * @return string the database parameter key value |
||||||
675 | */ |
||||||
676 | public function getAutoLoadValueFalse() |
||||||
677 | { |
||||||
678 | return $this->_autoLoadValueFalse; |
||||||
679 | } |
||||||
680 | |||||||
681 | /** |
||||||
682 | * @param string $value database parameter key value |
||||||
683 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
684 | */ |
||||||
685 | public function setAutoLoadValueFalse($value) |
||||||
686 | { |
||||||
687 | if ($this->_initialized) { |
||||||
688 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'AutoLoadValueFalse'); |
||||||
689 | } |
||||||
690 | $this->_autoLoadValueFalse = TPropertyValue::ensureString($value); |
||||||
691 | } |
||||||
692 | |||||||
693 | /** |
||||||
694 | * @return bool whether the paramter DB table should be automatically created if not exists. Defaults to true. |
||||||
695 | * @see setAutoCreateParamTable |
||||||
696 | */ |
||||||
697 | public function getAutoCreateParamTable() |
||||||
698 | { |
||||||
699 | return $this->_autoCreate; |
||||||
700 | } |
||||||
701 | |||||||
702 | /** |
||||||
703 | * @param bool $value whether the parameter DB table should be automatically created if not exists. |
||||||
704 | * @see setTableName |
||||||
705 | */ |
||||||
706 | public function setAutoCreateParamTable($value) |
||||||
707 | { |
||||||
708 | $this->_autoCreate = TPropertyValue::ensureBoolean($value); |
||||||
709 | } |
||||||
710 | |||||||
711 | /** |
||||||
712 | * @return null|callable|string |
||||||
713 | */ |
||||||
714 | public function getSerializer() |
||||||
715 | { |
||||||
716 | return $this->_serializer; |
||||||
717 | } |
||||||
718 | |||||||
719 | /** |
||||||
720 | * Serializer sets the type of serialization of objects and arrays in parameters |
||||||
721 | * to and from the database. 'php' uses serialze and unserialize. 'json' uses |
||||||
722 | * json_encode and json_decade. or you can provide your own callable to serialized |
||||||
723 | * and unserialize objects and arrays. |
||||||
724 | * @param callable|string $value the type of un/serialization. |
||||||
725 | * @throws \Prado\Exceptions\TInvalidOperationException if the module is initialized |
||||||
726 | * @throws \Prado\Exceptions\TInvalidDataTypeException if the $value is not 'php', 'json', or a callable |
||||||
727 | */ |
||||||
728 | public function setSerializer($value) |
||||||
729 | { |
||||||
730 | if ($this->_initialized) { |
||||||
731 | throw new TInvalidOperationException('dbparametermodule_property_unchangeable', 'Serializer'); |
||||||
732 | } |
||||||
733 | if ($value !== self::SERIALIZE_PHP && $value !== self::SERIALIZE_JSON && !is_callable($value)) { |
||||||
734 | throw new TInvalidDataTypeException('dbparametermodule_serializer_not_callable'); |
||||||
735 | } |
||||||
736 | $this->_serializer = $value; |
||||||
737 | } |
||||||
738 | |||||||
739 | /** |
||||||
740 | * @return bool whether the parameter DB table should be automatically created if not exists. Defaults to true. |
||||||
741 | */ |
||||||
742 | public function getCaptureParameterChanges() |
||||||
743 | { |
||||||
744 | return $this->_autoCapture; |
||||||
745 | } |
||||||
746 | |||||||
747 | /** |
||||||
748 | * @param bool $value whether the parameter DB table should be automatically created if not exists. |
||||||
749 | */ |
||||||
750 | public function setCaptureParameterChanges($value) |
||||||
751 | { |
||||||
752 | $this->_autoCapture = TPropertyValue::ensureBoolean($value); |
||||||
753 | } |
||||||
754 | } |
||||||
755 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.