Skip to content

Commit

Permalink
new logging functionality and DataManager compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
finanalyst committed Jun 24, 2018
1 parent 281a4c0 commit 8e3910b
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 116 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# v1.4.0
## 23 June 2018
1. [](#enhancement)
* More logging options, allowing for the SELECT, INSERT and UPDATE stanzas (in addition to Errors)
to be trapped.
* Append the logged data to the directory `user/data/sqlite` as a 'log.txt' file
* This allows an Administrator to view the data from within the Admin panel using the DataManager plugin.
2. [](#change of configuration)
* The default configuration for the placement of the sqlite3 database is now `user/data/sqlite`

# v1.3.0
## 11 June 2018
1. [](#enhancement)
Expand Down
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ You should now have all the plugin files under
and [Problems](https://github.com/getgrav/grav-plugin-problems) to operate.
The plugin also requires that the **SQLite3** extension is available with the version of php operating on your site.

### Database Installation
An adminstrator must create a directory for the database and place within it the *sqlite3* database file. It is recommended that the directory is `user/data/sqlite` (see configuration).

## Configuration

Expand All @@ -36,18 +38,32 @@ Here is the default configuration and an explanation of available options:

```yaml
enabled: true
database_route: data
database_route: data/sqlite
database_name: db.sqlite3
error_logging: false
logging: false
all_logging: false # this option only becomes active when logging is True
error_logging: false # this option only becomes active is False
select_logging: false
insert_logging: false
update_logging: false
```
- `enabled` turns on the plugin for the whole site. If `false`, then making it active on a page will have no effect.
- `database_route` is the Grav route (relative to the 'user' subdirectory) to the location of the `SQLite3` database.
- `database_name` is the full name (typically with the extension .sqlite3) of the database file. It is the responsibility of the site developer/maintainer to create the database.
- `error_logging` when false, nothing extra happens. When `true`, the SQL errors are logged to the file `sqlite_errors.txt` in the directory given by `database_route`. If however there is an error in setting `database_route`,
then the directory is `user/data`
- `logging` when false, nothing extra happens. When `true`, SQL related data is logged to a file called `sqlite.txt` in the directory given by `database_route`. If however there is an error in setting `database_route`,
then the directory is `user/data/sqlite`.

>SUGGESTION: If the DataManager plugin is installed and the default route is retained, then the SQL logs can be viewed
from the Admin panel.

- `all_logging` only become active when `logging` is enabled. If true, then all stanzas and errors are recorded.
- `error_logging` only becomes active when `logging` is enabled and `all_logging` is not enabled.
- `select_logging` only becomes active when `logging` is enabled and `all_logging` is not enabled.
- `insert_logging` only becomes active when `logging` is enabled and `all_logging` is not enabled.
- `update_logging` only becomes active when `logging` is enabled and `all_logging` is not enabled.

>NOTE: The database must exist. If it does not, then an error is generated.
`error_logging` should not be used in production settings as it writes to the hard drive, slowing performance.
`logging` should not be used in production settings as it writes to the hard drive, slowing performance.

### Per page configuration
Shortcodes can be enabled separately using the `shortcode-core` configuration. To disable shortcodes being used on all pages, but only used on selected pages, configure the shortcode-core plugin inside the Admin panel with `enabled=true` and `active=false`. Then on each page where shortcodes are used, include in the front section of the page:
Expand Down
71 changes: 67 additions & 4 deletions blueprints.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Sqlite
version: '1.3.0'
version: '1.4.0'
description: Plugin to select, update and insert into an sqlite3 database
icon: database
author:
Expand All @@ -26,7 +26,7 @@ form:
default: data
label: PLUGIN_SQLITE.DATABASE_ROUTE
help: PLUGIN_SQLITE.DATABASE_ROUTE_HELP
error_logging:
logging:
type: toggle
highlight: 0
default: 0
Expand All @@ -35,5 +35,68 @@ form:
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.ERROR_LOGGING
help: PLUGIN_SQLITE.ERROR_LOGGING_HELP
label: PLUGIN_SQLITE.LOGGING
help: PLUGIN_SQLITE.LOGGING_HELP
log_check:
type: conditional
condition: config.plugins.sqlite.logging
fields:
all_logging:
type: toggle
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.ALL_LOGGING
help: PLUGIN_SQLITE.ALL_LOGGING_HELP
discrete_logging:
type: conditional
condition: "config.plugins.sqlite.logging and not config.plugins.sqlite.all_logging "
fields:
error_logging:
type: toggle
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.ERROR_LOGGING
help: PLUGIN_SQLITE.ERROR_LOGGING_HELP
select_logging:
type: toggle
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.SELECT_LOGGING
help: PLUGIN_SQLITE.SELECT_LOGGING_HELP
insert_logging:
type: toggle
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.INSERT_LOGGING
help: PLUGIN_SQLITE.INSERT_LOGGING_HELP
update_logging:
type: toggle
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
label: PLUGIN_SQLITE.UPDATE_LOGGING
help: PLUGIN_SQLITE.UPDATE_LOGGING_HELP
14 changes: 12 additions & 2 deletions languages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,15 @@ en:
SQL_ERROR_3: generates the error.
UPDATE_WHERE: A where expression is mandatory (either as a parameter or as a form field) when using an "sql-update" Form action.
UPDATE_ERROR: The following UPDATE error was generated:<BR>%s
ERROR_LOGGING: Turn on Logging. (Not for production!!)
ERROR_LOGGING_HELP: Log file is saved when an error is detected in DATABASE_ROUTE, or /user/data if former fails.
LOGGING: Turn on Logging. (Not for production!!)
LOGGING_HELP: Log file is appended when an error is detected in DATABASE_ROUTE, or /user/data if former fails.
ALL_LOGGING: Turn on All Logging.
ALL_LOGGING_HELP: Log file is appended when an error is detected in DATABASE_ROUTE, or /user/data if former fails.
ERROR_LOGGING: Turn on Error Logging.
ERROR_LOGGING_HELP: Log file is appended when an error is detected in DATABASE_ROUTE, or /user/data if former fails.
SELECT_LOGGING: Turn on Select Logging.
SELECT_LOGGING_HELP: Log file is appended when a SELECT stanza is sent to database.
INSERT_LOGGING: Turn on Insert Logging.
INSERT_LOGGING_HELP: Log file is appended when an INSERT stanza is sent to database.
UPDATE_LOGGING: Turn on Update Logging.
UPDATE_LOGGING_HELP: Log file is appended when an UPDATE stanza is sent to database.
154 changes: 81 additions & 73 deletions shortcodes/SqlTableShortcode.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,84 +6,92 @@

class SqlTableShortcode extends Shortcode
{
public function init()
{
$this->shortcode->getHandlers()->add('sql-table', function(ShortcodeInterface $sc) {
if ( isset($this->grav['sqlite']['error']) && $this->grav['sqlite']['error'] ) {
if ($this->grav['sqlite']['logging']) {
$this->log_error($this->grav['sqlite']['error']);
}
return
$this->twig->processTemplate(
'partials/sql-db-error.html.twig',
[ 'message' => $this->grav['sqlite']['error']
]);
}
// database exists
$s = $sc->getContent();
// process any twig variables in the SQL stanza
$s = $this->grav['twig']->processString($s);
$stanza = html_entity_decode(preg_replace('/\<\/?p.*?\>|\n/i',' ',$s)); // remove <p> embedded by markdown
$params = $sc->getParameters();
$db = $this->grav['sqlite']['db'];
try {
$query = $db->query($stanza);
if ( ! $query ) throw new \Exception('No sql output from ' . $stanza);
$fields = array();
$cols = $query->numColumns();
if ( $cols < 1 ) throw new \Exception('No columns from ' . $stanza);
for ( $i = 0; $i < $cols; $i ++) {
array_push($fields, $query->columnName($i));
}
$rows = array();
while ( $row = $query->fetchArray(SQLITE3_ASSOC) ) {
array_push($rows,$row);
}
// first check whether json option is present, if so, ignore other options
if ( array_key_exists( 'json', $params) ) {
$output = $this->twig->processTemplate('partials/sql-json.html.twig',
[
'rows' => $rows
]);
} else {
// find if there are hidden columns
$hidden = array();
if ( isset( $params['hidden'])) {
$hidden = array_fill_keys(preg_split('/\s+/', $params['hidden'] ), 1);
const ERROR = 2; // binary flags for each log type
const SELECT = 4;
public function init()
{
$this->shortcode->getHandlers()->add('sql-table', function(ShortcodeInterface $sc) {
if ( isset($this->grav['sqlite']['error']) && $this->grav['sqlite']['error'] ) {
$this->log($this->grav['sqlite']['error']);
return
$this->twig->processTemplate(
'partials/sql-db-error.html.twig',
[ 'message' => $this->grav['sqlite']['error']
]);
}
$output = $this->twig->processTemplate('partials/sql-table.html.twig',
[
'fields' => $fields,
'rows' => $rows,
'hidden' => $hidden,
'class' => isset( $params['class']) ? $params['class'] : '',
'id' => isset($params['id']) ? $param['id'] : ''
]);
}
return $output;
} catch( \Exception $e) {
if ($this->grav['sqlite']['logging']) {
$this->log_error('message: ' . $e->getMessage() . "\ncontent: $stanza");
}
return
$this->twig->processTemplate(
'partials/sql-sql-error.html.twig',
[
'message' => $e->getMessage(),
'content' => $stanza
]);
}
// database exists
$s = $sc->getContent();
// process any twig variables in the SQL stanza
$s = $this->grav['twig']->processString($s);
$stanza = html_entity_decode(preg_replace('/\<\/?p.*?\>\s*|\n\s*/i',' ',$s)); // remove <p> embedded by markdown
$this->log(self::SELECT, $stanza);
$params = $sc->getParameters();
$db = $this->grav['sqlite']['db'];
try {
$query = $db->query($stanza);
if ( ! $query ) throw new \Exception('No sql output from ' . $stanza);
$fields = array();
$cols = $query->numColumns();
if ( $cols < 1 ) throw new \Exception('No columns from ' . $stanza);
for ( $i = 0; $i < $cols; $i ++) {
array_push($fields, $query->columnName($i));
}
$rows = array();
while ( $row = $query->fetchArray(SQLITE3_ASSOC) ) {
array_push($rows,$row);
}
// first check whether json option is present, if so, ignore other options
if ( array_key_exists( 'json', $params) ) {
$output = $this->twig->processTemplate('partials/sql-json.html.twig',
[
'rows' => $rows
]);
} else {
// find if there are hidden columns
$hidden = array();
if ( isset( $params['hidden'])) {
$hidden = array_fill_keys(preg_split('/\s+/', $params['hidden'] ), 1);
}
$output = $this->twig->processTemplate('partials/sql-table.html.twig',
[
'fields' => $fields,
'rows' => $rows,
'hidden' => $hidden,
'class' => isset( $params['class']) ? $params['class'] : '',
'id' => isset($params['id']) ? $param['id'] : ''
]
);
}
return $output;
} catch( \Exception $e) {
$this->log(self::ERROR, 'message: ' . $e->getMessage() . "\ncontent: $stanza");
return
$this->twig->processTemplate(
'partials/sql-sql-error.html.twig',
[
'message' => $e->getMessage(),
'content' => $stanza
]
);
}
});
}

public function log_error(String $msg) {
$path = $this->grav['sqlite']['path'] . 'sqlite_errors.txt';
public function log($type, $msg) {
$log_val =$this->grav['sqlite']['logging'];
if ( $log_val == 0 ) return;

$path = $this->grav['sqlite']['path'] . DS . 'sqlite.html';
$datafh = File::instance($path);
if ( file_exists($path) ) {
$datafh->save($datafh->content() . "\n" . $msg);
} else {
$datafh->save($msg);
chmod($path, 0666);
if ( ($log_val & self::ERROR) && ($type & self::ERROR)
|| ($log_val & self::SELECT) && ($type & self::SELECT)
) {
if ( file_exists($path) ) {
$datafh->save($datafh->content() . '<br><span style="color:blue">' . date('Y-m-d:H:i') . '</span>: ' . $msg);
} else {
$datafh->save('<span style="color:blue">' . date('Y-m-d:H:i') . '</span>: ' . $msg);
chmod($path, 0666);
}
}
}
}
Loading

0 comments on commit 8e3910b

Please sign in to comment.