From bb210afa4f9f3552c036dd91371f6ff5c472e07f Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Tue, 31 Dec 2013 11:59:23 -0200 Subject: [PATCH 01/10] Compatibility width Cake 2.4. Field user_agent added. --- Config/Schema/schema.php | 3 +- Config/database_log.php.example | 12 ++ Controller/DatabaseLogAppController.php | 8 + Controller/LogsController.php | 2 +- Lib/Log/Engine/DatabaseLog.php | 8 +- Model/DatabaseLogAppModel.php | 204 +++++++++++++++++++ Model/Log.php | 3 +- Test/Case/Model/LogTest.php | 4 +- Test/Case/controllers/LogsControllerTest.php | 2 +- Test/Case/models/LogTest.php | 4 +- View/Elements/admin_filter.ctp | 4 +- View/Logs/admin_index.ctp | 8 +- View/Logs/admin_view.ctp | 9 +- composer.json | 8 +- readme.markdown | 15 +- webroot/css/style.css | 130 ++++++------ 16 files changed, 328 insertions(+), 96 deletions(-) create mode 100644 Config/database_log.php.example create mode 100644 Controller/DatabaseLogAppController.php create mode 100644 Model/DatabaseLogAppModel.php diff --git a/Config/Schema/schema.php b/Config/Schema/schema.php index 09d7c52..c453dba 100644 --- a/Config/Schema/schema.php +++ b/Config/Schema/schema.php @@ -1,5 +1,5 @@ array('type' => 'string', 'null' => true, 'default' => null, 'length' => 50, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 'uri' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 'refer' => array('type' => 'string', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), + 'user_agent' => array('type' => 'text', 'null' => true, 'default' => null, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'type' => array('column' => 'type', 'unique' => 0), diff --git a/Config/database_log.php.example b/Config/database_log.php.example new file mode 100644 index 0000000..9ebbd25 --- /dev/null +++ b/Config/database_log.php.example @@ -0,0 +1,12 @@ + array( + 'write' => 'default', //DataSource to write to. + 'read' => 'default', //Dadtasource to read from. + ) +); diff --git a/Controller/DatabaseLogAppController.php b/Controller/DatabaseLogAppController.php new file mode 100644 index 0000000..dbaf39a --- /dev/null +++ b/Controller/DatabaseLogAppController.php @@ -0,0 +1,8 @@ +request->params['named']) ? $this->request->params['named'] : array(); + $data = isset($this->request->data[$key]) ? $this->request->data[$key] : array(); + $this->request->params['named'] = array_merge($data, $params); + } +} \ No newline at end of file diff --git a/Controller/LogsController.php b/Controller/LogsController.php index 3465d2d..d7283b4 100644 --- a/Controller/LogsController.php +++ b/Controller/LogsController.php @@ -1,5 +1,5 @@ 'DatabaseLogger.DatabaseLogger', - 'model' => 'CustomLogModel' //'DatabaseLogger.Log' by default + 'engine' => 'DatabaseLog.DatabaseLog', + 'model' => 'CustomLogModel' //'DatabaseLog.Log' by default )); */ App::uses('ClassRegistry', 'Utility'); App::uses('CakeLogInterface','Log'); -App::uses('Log', 'DatabaseLogger.Model'); +App::uses('Log', 'DatabaseLog.Model'); class DatabaseLog implements CakeLogInterface{ /** @@ -34,7 +34,7 @@ class DatabaseLog implements CakeLogInterface{ * Contruct the model class */ function __construct($options = array()){ - $this->model = isset($options['model']) ? $options['model'] : 'DatabaseLogger.Log'; + $this->model = isset($options['model']) ? $options['model'] : 'DatabaseLog.Log'; $this->Log = ClassRegistry::init($this->model); } diff --git a/Model/DatabaseLogAppModel.php b/Model/DatabaseLogAppModel.php new file mode 100644 index 0000000..69192d4 --- /dev/null +++ b/Model/DatabaseLogAppModel.php @@ -0,0 +1,204 @@ + 'default', + 'read' => 'default', + ); + + /** + * Set the default datasource to the read setup in config + */ + public function __construct($id = false, $table = null, $ds = null) { + if(Configure::load('database_log')){ + $this->configs = Configure::read('DatabaseLog'); + } + parent::__construct($id, $table, $ds); + $this->setDataSourceRead(); + } + + /** + * Overwrite save to write to the datasource defined in config + */ + public function save($data = null, $validate = true, $fieldList = array()) { + $this->setDataSourceWrite(); + $retval = parent::save($data, $validate, $fieldList); + $this->setDataSourceRead(); + return $retval; + } + + /** + * Overwrite delete to delete to the datasource defined in config + */ + public function delete($id = null, $cascade = true) { + $this->setDataSourceWrite(); + $retval = parent::delete($id, $cascade); + $this->setDataSourceRead(); + return $retval; + } + + /** + * Overwrite find so I can do some nice things with it. + * @param string find type + * - last : find last record by created date + * @param array of options + */ + function find($type = 'first', $options = array()){ + switch($type){ + case 'last': + $options = array_merge( + $options, + array('order' => "{$this->alias}.{$this->primaryKey} DESC") + ); + return parent::find('first', $options); + default: + return parent::find($type, $options); + } + } + + /** + * return conditions based on searchable fields and filter + * @param string filter + * @return conditions array + */ + function generateFilterConditions($filter = NULL, $pre = ''){ + $retval = array(); + if($filter){ + foreach($this->searchFields as $field){ + $retval['OR']["$field LIKE"] = '%' . $filter . '%'; + } + } + return $retval; + } + + /** + * Set the datasource to be read + * if being tested, don't change, otherwise change to what we read + */ + private function setDataSourceRead(){ + if($this->useDbConfig != 'test'){ + $this->setDataSource($this->configs['read']); + } + } + + /** + * Set the datasource to be write + * if being tested, don't change, otherwise change to what we config + */ + private function setDataSourceWrite(){ + if($this->useDbConfig != 'test'){ + $this->setDataSource($this->configs['write']); + } + } + + /** + * Export the current model table into a csv file. + */ + function export($options = array(), $showHeaders = true){ + $default_options = array( + 'contain' => array() + ); + + $options = array_merge($default_options, $options); + + $columns = array_keys($this->schema()); + $headers = array(); + foreach($columns as $column){ + $headers[$this->alias][$column] = $column; + } + $data = $this->find('all', $options); + + array_unshift($data, $headers); + return $data; + } + + /** + * Generate a find or the conditions for a find + * based on the search criteria passed into it. + * + * @param array params to search on + * @param array of options + * - order => array of how to order it (Model.created ASC by default) + * - recursive => int of recursive type (0 by default) + * - find => 'all' for find all to be preformed, 'first' for find first to be preformed, false if you just want conditions (false by default) + * - fields => array of fields to select. (* by default) + */ + function search($params = array(), $options = array()){ + $options = array_merge( + array( + 'order' => array("{$this->alias}.created ASC"), + 'recursive' => 0, + 'fields' => array('*'), + 'find' => false, + ), + $options + ); + if(empty($this->_fields)){ + $this->_fields = $this->getColumnTypes(); + } + + //search through params, make sure there is a field that coresponds. + $conditions = array(); + $field_options = array('LIKE','>=','<=','>','<'); + foreach($params as $key => $value){ + if(isset($this->_fields[$key]) && $value){ + if(is_array($value)){ + if(!empty($value['year'])){ + $conditions['AND']["{$this->alias}.$key"] = $value['year'] ."-". $value['month'] . "-" . $value['day']; + } + } else { + $values = explode('[or]', $value); + foreach($values as $value){ + $query_opt = (strpos($value, '%') !== false || strpos($value, '*') !== false) ? ' LIKE' : ''; + if(strpos($value, '*') !== false){ + $value = str_replace('*','%', $value); + } + if(strpos($value, '!') === 0){ + $query_opt = ' !='; + $value = str_replace('!','', $value); + } + if($value == 'null'){ + $value = ''; + } + if(count($values) == 1){ + $conditions['AND']["{$this->alias}.$key$query_opt"] = $value; + } else { + $conditions['AND']['OR'][] = array("{$this->alias}.$key$query_opt" => $value); + } + } + } + } elseif(isset($this->_fields['modified']) && ($key == 'start_date' || $key == 'end_date') && !empty($value['year'])){ + $opt = $key == 'start_date' ? '>=' : '<='; + $conditions['AND']["{$this->alias}.created $opt"] = $params[$key]['year'] ."-". $params[$key]['month'] . "-" . $params[$key]['day']; + } else { + foreach($field_options as $opt){ + if(strpos($key, $opt)){ + $field = substr($key, 0, strlen($key) - (strlen($opt) + 1)); + if(isset($this->_fields[$field]) && $value){ + $conditions['AND']["{$this->alias}.$key"] = $value; + break; + } + } + } + } + } + if($options['find']){ + return $this->find($options['find'], array( + 'conditions' => $conditions, + 'order' => $options['order'], + 'recursive' => $options['recursive'], + 'fields' => $options['fields'], + )); + } else { + return $conditions; + } + } +} \ No newline at end of file diff --git a/Model/Log.php b/Model/Log.php index daf64e9..61f633f 100755 --- a/Model/Log.php +++ b/Model/Log.php @@ -1,5 +1,5 @@ data[$this->alias]['hostname'] = env('HTTP_HOST'); $this->data[$this->alias]['uri'] = env('REQUEST_URI'); $this->data[$this->alias]['refer'] = env('HTTP_REFERER'); + $this->data[$this->alias]['user_agent'] = env('HTTP_USER_AGENT'); return true; } diff --git a/Test/Case/Model/LogTest.php b/Test/Case/Model/LogTest.php index a0a9b56..bb9f185 100755 --- a/Test/Case/Model/LogTest.php +++ b/Test/Case/Model/LogTest.php @@ -1,9 +1,9 @@ Log = ClassRegistry::init('Log'); diff --git a/Test/Case/controllers/LogsControllerTest.php b/Test/Case/controllers/LogsControllerTest.php index 619b8dc..ca437a0 100755 --- a/Test/Case/controllers/LogsControllerTest.php +++ b/Test/Case/controllers/LogsControllerTest.php @@ -1,6 +1,6 @@ Log = ClassRegistry::init('Log'); diff --git a/View/Elements/admin_filter.ctp b/View/Elements/admin_filter.ctp index e70a066..735e9ca 100755 --- a/View/Elements/admin_filter.ctp +++ b/View/Elements/admin_filter.ctp @@ -1,4 +1,4 @@ -Html->script('/database_logger/js/clear_default'); ?> +Html->script('/database_log/js/clear_default'); ?>
Form->create($model, array('inputDefaults' => array('label' => false,'div' => false))); echo $this->Form->input('filter', array('label' => false, 'value' => "$model Search", 'class' => 'clear_default')); - echo $this->Form->submit('/database_logger/img/search_button.gif', array('div' => false)); + echo $this->Form->submit('/database_log/img/search_button.gif', array('div' => false)); echo $this->Form->end(); } ?> diff --git a/View/Logs/admin_index.ctp b/View/Logs/admin_index.ctp index 74c98ff..feb34db 100755 --- a/View/Logs/admin_index.ctp +++ b/View/Logs/admin_index.ctp @@ -1,6 +1,6 @@ -Html->css('/database_logger/css/style'); ?> -
- element('admin_filter', array('plugin' => 'database_logger', 'model' => 'Log')); ?> +Html->css('/database_log/css/style'); ?> +
+ element('admin_filter', array('plugin' => 'database_log', 'model' => 'Log')); ?>

@@ -29,6 +29,6 @@
- element('paging', array('plugin' => 'database_logger')); ?> + element('paging', array('plugin' => 'database_log')); ?>
\ No newline at end of file diff --git a/View/Logs/admin_view.ctp b/View/Logs/admin_view.ctp index 1701a5f..dcc0549 100755 --- a/View/Logs/admin_view.ctp +++ b/View/Logs/admin_view.ctp @@ -1,5 +1,5 @@ -Html->css('/database_logger/css/style'); ?> -
+Html->css('/database_log/css/style'); ?> +

@@ -28,6 +28,11 @@   + > + > + +   + > > diff --git a/composer.json b/composer.json index a6211ab..1f63288 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "CakePHP Database Logger Plugin", "type": "cakephp-plugin", "keywords": ["cakephp", "database", "logging", "logs", "plugin"], - "homepage": "https://github.com/webtechnick/CakePHP-DatabaseLogger-Plugin", + "homepage": "https://github.com/webtechnick/CakePHP-DatabaseLog-Plugin", "license": "MIT", "authors": [ { @@ -13,8 +13,8 @@ } ], "support": { - "issues": "https://github.com/webtechnick/CakePHP-DatabaseLogger-Plugin/issues", - "source": "https://github.com/webtechnick/CakePHP-DatabaseLogger-Plugin" + "issues": "https://github.com/webtechnick/CakePHP-DatabaseLog-Plugin/issues", + "source": "https://github.com/webtechnick/CakePHP-DatabaseLog-Plugin" }, "require": { "php": ">=5.2.0", @@ -24,6 +24,6 @@ "branch-alias": { "dev-master": "2.x-dev" }, - "installer-name": "DatabaseLogger" + "installer-name": "DatabaseLog" } } \ No newline at end of file diff --git a/readme.markdown b/readme.markdown index 8271fe9..b681ab5 100644 --- a/readme.markdown +++ b/readme.markdown @@ -1,6 +1,6 @@ # Database CakePHP Plugin * Author: Nick Baker -* Version: 1.3 +* Version: 1.4.1 * License: MIT * Website: @@ -10,6 +10,7 @@ Database CakeLogger for CakePHP 2.x applications. Easy setup. Ideal for multi is just not convinient. Simple admin interface to view/delete logs included. ## Changelog +* 1.4.1 Compatible with CakePHP 2.4. Field user_agent added. * 1.4.0 Compatible with CakePHP 2.4 * 1.3.0 New configuration file to change default read, write datasources. * 1.2.0 Now using FULLTEXT search on messages, better indexes. Update your schema. @@ -18,9 +19,9 @@ is just not convinient. Simple admin interface to view/delete logs included. ## Install -Clone the repository into your `app/Plugin/DatabaseLogger` directory: +Clone the repository into your `app/Plugin/DatabaseLog` directory: - $ git clone git://github.com/webtechnick/CakePHP-DatabaseLogger-Plugin.git app/Plugin/DatabaseLogger + $ git clone git://github.com/webtechnick/CakePHP-DatabaseLogger-Plugin.git app/Plugin/DatabaseLog Run the schema into your database: @@ -28,10 +29,10 @@ Run the schema into your database: ## Setup -Create a config file in `app/Config/database_logger` with the following (example file in plugin.) +Create a config file in `app/Config/database_log` with the following (example file in plugin.) $config = array( - 'DatabaseLogger' => array( + 'DatabaseLog' => array( 'write' => 'default', //DataSource to write to. 'read' => 'default', //Datasource to read from. ) @@ -42,7 +43,7 @@ Pro Tip: You can read from a different datasource than you write to, and they bo Update the file `app/Config/bootstrap.php` with the following configurations like so: App::uses('CakeLog','Log'); - CakeLog::config('default', array('engine' => 'DatabaseLogger.DatabaseLogger')); + CakeLog::config('default', array('engine' => 'DatabaseLog.DatabaseLog')); ## Usage @@ -51,4 +52,4 @@ Anywhere in your app where you call log() or CakeLog::write the database logger $this->log('This is a detailed message logged to the database','error'); CakeLog::write('error', 'This is a detailed message logged to the database'); -Navigate to `http://www.example.com/admin/database_logger/logs` to view/search/delete your logs. \ No newline at end of file +Navigate to `http://www.example.com/admin/database_log/logs` to view/search/delete your logs. \ No newline at end of file diff --git a/webroot/css/style.css b/webroot/css/style.css index 49f8476..0746c7e 100644 --- a/webroot/css/style.css +++ b/webroot/css/style.css @@ -1,27 +1,27 @@ /** containers **/ -div.database_logger_plugin div.form, -div.database_logger_plugin div.index, -div.database_logger_plugin div.view { +div.database_log_plugin div.form, +div.database_log_plugin div.index, +div.database_log_plugin div.view { border-left:1px solid #666; padding:10px 2%; min-height: 300px; } -div.database_logger_plugin div.actions { +div.database_log_plugin div.actions { float:left; width:16%; padding:10px 1.5%; } -div.database_logger_plugin div.actions h3 { +div.database_log_plugin div.actions h3 { padding-top:0; color:#777; } -div.database_logger_plugin #admin_filter form input[type="image"]{ +div.database_log_plugin #admin_filter form input[type="image"]{ position: relative; top: 10px; } /** Tables **/ -div.database_logger_plugin table { +div.database_log_plugin table { background: #fff; border-right:0; clear: both; @@ -29,186 +29,186 @@ div.database_logger_plugin table { margin-bottom: 10px; width: 100%; } -div.database_logger_plugin th { +div.database_log_plugin th { border:0; border-bottom:2px solid #555; text-align: left; padding:4px; } -div.database_logger_plugin th a { +div.database_log_plugin th a { display: block; padding: 2px 4px; text-decoration: none; } -div.database_logger_plugin th a.asc:after { +div.database_log_plugin th a.asc:after { content: ' ⇣'; } -div.database_logger_plugin th a.desc:after { +div.database_log_plugin th a.desc:after { content: ' ⇡'; } -div.database_logger_plugin table tr td { +div.database_log_plugin table tr td { background: #fff; padding: 6px; text-align: left; vertical-align: top; border-bottom:1px solid #ddd; } -div.database_logger_plugin table tr:nth-child(2n) td { +div.database_log_plugin table tr:nth-child(2n) td { background: #f5f5f5; } -div.database_logger_plugin table .altrow td { +div.database_log_plugin table .altrow td { background: #f5f5f5; } -div.database_logger_plugin td.actions { +div.database_log_plugin td.actions { text-align: center; white-space: nowrap; } -div.database_logger_plugin table td.actions a { +div.database_log_plugin table td.actions a { margin: 0px 6px; padding:2px 5px; } /** Paging **/ -div.database_logger_plugin div.paging { +div.database_log_plugin div.paging { background:#fff; color: #ccc; margin-top: 1em; clear:both; } -div.database_logger_plugin div.paging span.disabled { +div.database_log_plugin div.paging span.disabled { color: #ddd; display: inline; } -div.database_logger_plugin div.paging span.current { +div.database_log_plugin div.paging span.current { color: #c73e14; } -div.database_logger_plugin div.paging span a { +div.database_log_plugin div.paging span a { } /** Scaffold View **/ -div.database_logger_plugin dl { +div.database_log_plugin dl { line-height: 2em; margin: 0em 0em; width: 60%; } -div.database_logger_plugin dl .altrow { +div.database_log_plugin dl .altrow { background: #f4f4f4; } -div.database_logger_plugin dt { +div.database_log_plugin dt { font-weight: bold; padding-left: 4px; vertical-align: top; } -div.database_logger_plugin dd { +div.database_log_plugin dd { margin-left: 10em; margin-top: -2em; vertical-align: top; } /** Forms **/ -div.database_logger_plugin form { +div.database_log_plugin form { clear: both; margin-right: 20px; padding: 0; width: 95%; } -div.database_logger_plugin fieldset { +div.database_log_plugin fieldset { border: 1px solid #ccc; margin-bottom: 1em; padding: 16px 20px; } -div.database_logger_plugin fieldset legend { +div.database_log_plugin fieldset legend { background:#fff; color: #e32; font-size: 160%; font-weight: bold; } -div.database_logger_plugin fieldset fieldset { +div.database_log_plugin fieldset fieldset { margin-top: 0px; margin-bottom: 20px; padding: 16px 10px; } -div.database_logger_plugin fieldset fieldset legend { +div.database_log_plugin fieldset fieldset legend { font-size: 120%; font-weight: normal; } -div.database_logger_plugin fieldset fieldset div { +div.database_log_plugin fieldset fieldset div { clear: left; margin: 0 20px; } -div.database_logger_plugin form div { +div.database_log_plugin form div { clear: both; margin-bottom: 1em; padding: .5em; vertical-align: text-top; } -div.database_logger_plugin form .input { +div.database_log_plugin form .input { color: #444; } -div.database_logger_plugin form .required { +div.database_log_plugin form .required { font-weight: bold; } -div.database_logger_plugin form .required label:after { +div.database_log_plugin form .required label:after { color: #e32; content: '*'; display:inline; } -div.database_logger_plugin form div.submit { +div.database_log_plugin form div.submit { border: 0; clear: both; margin-top: 10px; } -div.database_logger_plugin label { +div.database_log_plugin label { display: block; font-size: 110%; margin-bottom:3px; } -div.database_logger_plugin input, div.database_logger_plugin textarea { +div.database_log_plugin input, div.database_log_plugin textarea { clear: both; font-size: 140%; font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif; padding: 1%; width:98%; } -div.database_logger_plugin #admin_filter input { +div.database_log_plugin #admin_filter input { clear: none; width: auto; } -div.database_logger_plugin select { +div.database_log_plugin select { clear: both; font-size: 120%; vertical-align: text-bottom; } -div.database_logger_plugin select[multiple=multiple] { +div.database_log_plugin select[multiple=multiple] { width: 100%; } -div.database_logger_plugin option { +div.database_log_plugin option { font-size: 120%; padding: 0 3px; } -div.database_logger_plugin input[type=checkbox] { +div.database_log_plugin input[type=checkbox] { clear: left; float: left; margin: 0px 6px 7px 2px; width: auto; } -div.database_logger_plugin div.checkbox label { +div.database_log_plugin div.checkbox label { display: inline; } -div.database_logger_plugin input[type=radio] { +div.database_log_plugin input[type=radio] { float:left; width:auto; margin: 0 3px 7px 0; } -div.database_logger_plugin div.radio label { +div.database_log_plugin div.radio label { margin: 0 0 6px 20px; } -div.database_logger_plugin input[type=submit] { +div.database_log_plugin input[type=submit] { display: inline; font-size: 110%; width: auto; } -div.database_logger_plugin form .submit input[type=submit] { +div.database_log_plugin form .submit input[type=submit] { background:#62af56; background: -webkit-gradient(linear, left top, left bottom, from(#a8ea9c), to(#62af56)); background-image: -moz-linear-gradient(top, #a8ea9c, #62af56); @@ -216,14 +216,14 @@ div.database_logger_plugin form .submit input[type=submit] { color: #000; text-shadow: #8cee7c 0px 1px 0px; } -div.database_logger_plugin form .submit input[type=submit]:hover { +div.database_log_plugin form .submit input[type=submit]:hover { background:#4ca83d; background: -webkit-gradient(linear, left top, left bottom, from(#85e573), to(#4ca83d)); background-image: -moz-linear-gradient(top, #85e573, #4ca83d); } /** Notices and Errors **/ -div.database_logger_plugin div.message { +div.database_log_plugin div.message { clear: both; color: #fff; font-size: 140%; @@ -232,13 +232,13 @@ div.database_logger_plugin div.message { background: #c73e14; padding: 5px; } -div.database_logger_plugin div.error-message { +div.database_log_plugin div.error-message { clear: both; color: #fff; font-weight: bold; background: #c73e14; } -div.database_logger_plugin p.error { +div.database_log_plugin p.error { background-color: #e32; color: #fff; font-family: Courier, monospace; @@ -247,12 +247,12 @@ div.database_logger_plugin p.error { padding: 0.8em; margin: 1em 0; } -div.database_logger_plugin p.error em { +div.database_log_plugin p.error em { color: #000; font-weight: normal; line-height: 140%; } -div.database_logger_plugin .notice { +div.database_log_plugin .notice { background: #ffcc00; color: #000; display: block; @@ -262,34 +262,34 @@ div.database_logger_plugin .notice { padding: 0.8em; margin: 1em 0; } -div.database_logger_plugin .success { +div.database_log_plugin .success { background: green; color: #fff; } /** Actions **/ -div.database_logger_plugin div.actions ul { +div.database_log_plugin div.actions ul { margin: 0; padding: 0; } -div.database_logger_plugin div.actions li { +div.database_log_plugin div.actions li { margin:0 0 0.5em 0; list-style-type: none; white-space: nowrap; padding: 0; } -div.database_logger_plugin div.actions ul li a { +div.database_log_plugin div.actions ul li a { font-weight: normal; display: block; clear: both; } -div.database_logger_plugin div.actions ul li a:hover { +div.database_log_plugin div.actions ul li a:hover { text-decoration: underline; } -div.database_logger_plugin input[type=submit], -div.database_logger_plugin div.actions ul li a, -div.database_logger_plugin td.actions a { +div.database_log_plugin input[type=submit], +div.database_log_plugin div.actions ul li a, +div.database_log_plugin td.actions a { font-weight:normal; padding: 4px 8px; background:#e6e49f; @@ -304,15 +304,15 @@ div.database_logger_plugin td.actions a { text-shadow: #fff 0px 1px 0px; min-width: 0; } -div.database_logger_plugin input[type=submit]:hover, -div.database_logger_plugin div.actions ul li a:hover, -div.database_logger_plugin td.actions a:hover { +div.database_log_plugin input[type=submit]:hover, +div.database_log_plugin div.actions ul li a:hover, +div.database_log_plugin td.actions a:hover { background: #f0f09a; background: -webkit-gradient(linear, left top, left bottom, from(#f7f7e1), to(#eeeca9)); } /** Related **/ -div.database_logger_plugin div.related { +div.database_log_plugin div.related { clear: both; display: block; } \ No newline at end of file From 4120e42c2a286e31ddc76f145c22487cdc5a1da1 Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 09:00:12 -0200 Subject: [PATCH 02/10] Fix export --- Controller/LogsController.php | 11 ++++--- View/Helper/CsvHelper.php | 61 +++++++++++++++++++++++++++++++++++ View/Helper/empty | 0 View/Logs/admin_export.ctp | 6 ++++ View/Logs/admin_index.ctp | 2 +- readme.markdown | 7 ++-- 6 files changed, 79 insertions(+), 8 deletions(-) create mode 100755 View/Helper/CsvHelper.php create mode 100755 View/Helper/empty create mode 100644 View/Logs/admin_export.ctp diff --git a/Controller/LogsController.php b/Controller/LogsController.php index d7283b4..b11fbca 100644 --- a/Controller/LogsController.php +++ b/Controller/LogsController.php @@ -2,7 +2,7 @@ class LogsController extends DatabaseLogAppController { var $name = 'Logs'; - var $helpers = array('Time','Icing.Csv'); + //var $helpers = array('Time','Icing.Csv'); var $paginate = array( 'order' => 'Log.id DESC', 'fields' => array( @@ -29,13 +29,14 @@ function admin_index($filter = null) { } function admin_export($filter = null){ - $this->layout = 'csv'; + //$this->layout = 'csv'; + $this->layout = false; if(!empty($this->data)){ $filter = $this->data['Log']['filter']; } - if($this->RequestHandler->ext != 'csv'){ - $this->redirect(array('action' => 'export', 'ext' => 'csv', $filter)); - } + //if($this->RequestHandler->ext != 'csv'){ + // $this->redirect(array('action' => 'export', 'ext' => 'csv', $filter)); + //} $this->dataToNamed(); $conditions = array_merge( $this->Log->search($this->request->params['named']), diff --git a/View/Helper/CsvHelper.php b/View/Helper/CsvHelper.php new file mode 100755 index 0000000..174ed36 --- /dev/null +++ b/View/Helper/CsvHelper.php @@ -0,0 +1,61 @@ +clear(); + } + + function clear() { + $this->line = array(); + $this->buffer = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+'); + } + + function addField($value) { + $this->line[] = $value; + } + + function endRow() { + $this->addRow($this->line); + $this->line = array(); + } + + function addRow($row) { + fputcsv($this->buffer, $row, $this->delimiter, $this->enclosure); + } + + function renderHeaders() { + header("Content-type:application/vnd.ms-excel"); + header("Content-disposition:attachment;filename=".$this->filename); + } + + function setFilename($filename) { + $this->filename = $filename; + if (strtolower(substr($this->filename, -4)) != '.csv') { + $this->filename .= '.csv'; + } + } + + function render($outputHeaders = true, $to_encoding = null, $from_encoding = "auto") { + if ($outputHeaders) { + if (is_string($outputHeaders)) { + $this->setFilename($outputHeaders); + } + $this->renderHeaders(); + } + rewind($this->buffer); + $output = stream_get_contents($this->buffer); + if ($to_encoding) { + $output = mb_convert_encoding($output, $to_encoding, $from_encoding); + } + return $this->output($output); + } +} + +?> \ No newline at end of file diff --git a/View/Helper/empty b/View/Helper/empty new file mode 100755 index 0000000..e69de29 diff --git a/View/Logs/admin_export.ctp b/View/Logs/admin_export.ctp new file mode 100644 index 0000000..8de3378 --- /dev/null +++ b/View/Logs/admin_export.ctp @@ -0,0 +1,6 @@ +Csv->addRow($row); +} +echo $this->Csv->render($filename); \ No newline at end of file diff --git a/View/Logs/admin_index.ctp b/View/Logs/admin_index.ctp index feb34db..a3988c4 100755 --- a/View/Logs/admin_index.ctp +++ b/View/Logs/admin_index.ctp @@ -1,8 +1,8 @@ Html->css('/database_log/css/style'); ?>
- element('admin_filter', array('plugin' => 'database_log', 'model' => 'Log')); ?>

+ element('admin_filter', array('plugin' => 'database_log', 'model' => 'Log')); ?> diff --git a/readme.markdown b/readme.markdown index b681ab5..d495deb 100644 --- a/readme.markdown +++ b/readme.markdown @@ -10,7 +10,7 @@ Database CakeLogger for CakePHP 2.x applications. Easy setup. Ideal for multi is just not convinient. Simple admin interface to view/delete logs included. ## Changelog -* 1.4.1 Compatible with CakePHP 2.4. Field user_agent added. +* 1.4.1 Compatible with CakePHP 2.4. Field user_agent added. Fix CSV export. * 1.4.0 Compatible with CakePHP 2.4 * 1.3.0 New configuration file to change default read, write datasources. * 1.2.0 Now using FULLTEXT search on messages, better indexes. Update your schema. @@ -52,4 +52,7 @@ Anywhere in your app where you call log() or CakeLog::write the database logger $this->log('This is a detailed message logged to the database','error'); CakeLog::write('error', 'This is a detailed message logged to the database'); -Navigate to `http://www.example.com/admin/database_log/logs` to view/search/delete your logs. \ No newline at end of file +Navigate to `http://www.example.com/admin/database_log/logs` to view/search/delete your logs. + +Warning: you should have added admin prefix for routes. +Configure::write('Routing.prefixes', array('admin')); \ No newline at end of file From 3694976a89a0c1d69e00170715d888bfae1be03d Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:36:57 -0200 Subject: [PATCH 03/10] Delete DatabaseLoggerAppController.php --- Controller/DatabaseLoggerAppController.php | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Controller/DatabaseLoggerAppController.php diff --git a/Controller/DatabaseLoggerAppController.php b/Controller/DatabaseLoggerAppController.php deleted file mode 100644 index 8bb856b..0000000 --- a/Controller/DatabaseLoggerAppController.php +++ /dev/null @@ -1,8 +0,0 @@ -request->params['named']) ? $this->request->params['named'] : array(); - $data = isset($this->request->data[$key]) ? $this->request->data[$key] : array(); - $this->request->params['named'] = array_merge($data, $params); - } -} \ No newline at end of file From 6eff51a6c7331be8d75cbd04825f7b97fd18242b Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:37:29 -0200 Subject: [PATCH 04/10] Delete DatabaseLoggerAppModel.php --- Model/DatabaseLoggerAppModel.php | 204 ------------------------------- 1 file changed, 204 deletions(-) delete mode 100644 Model/DatabaseLoggerAppModel.php diff --git a/Model/DatabaseLoggerAppModel.php b/Model/DatabaseLoggerAppModel.php deleted file mode 100644 index bafbf45..0000000 --- a/Model/DatabaseLoggerAppModel.php +++ /dev/null @@ -1,204 +0,0 @@ - 'default', - 'read' => 'default', - ); - - /** - * Set the default datasource to the read setup in config - */ - public function __construct($id = false, $table = null, $ds = null) { - if(Configure::load('database_logger')){ - $this->configs = Configure::read('DatabaseLogger'); - } - parent::__construct($id, $table, $ds); - $this->setDataSourceRead(); - } - - /** - * Overwrite save to write to the datasource defined in config - */ - public function save($data = null, $validate = true, $fieldList = array()) { - $this->setDataSourceWrite(); - $retval = parent::save($data, $validate, $fieldList); - $this->setDataSourceRead(); - return $retval; - } - - /** - * Overwrite delete to delete to the datasource defined in config - */ - public function delete($id = null, $cascade = true) { - $this->setDataSourceWrite(); - $retval = parent::delete($id, $cascade); - $this->setDataSourceRead(); - return $retval; - } - - /** - * Overwrite find so I can do some nice things with it. - * @param string find type - * - last : find last record by created date - * @param array of options - */ - function find($type = 'first', $options = array()){ - switch($type){ - case 'last': - $options = array_merge( - $options, - array('order' => "{$this->alias}.{$this->primaryKey} DESC") - ); - return parent::find('first', $options); - default: - return parent::find($type, $options); - } - } - - /** - * return conditions based on searchable fields and filter - * @param string filter - * @return conditions array - */ - function generateFilterConditions($filter = NULL, $pre = ''){ - $retval = array(); - if($filter){ - foreach($this->searchFields as $field){ - $retval['OR']["$field LIKE"] = '%' . $filter . '%'; - } - } - return $retval; - } - - /** - * Set the datasource to be read - * if being tested, don't change, otherwise change to what we read - */ - private function setDataSourceRead(){ - if($this->useDbConfig != 'test'){ - $this->setDataSource($this->configs['read']); - } - } - - /** - * Set the datasource to be write - * if being tested, don't change, otherwise change to what we config - */ - private function setDataSourceWrite(){ - if($this->useDbConfig != 'test'){ - $this->setDataSource($this->configs['write']); - } - } - - /** - * Export the current model table into a csv file. - */ - function export($options = array(), $showHeaders = true){ - $default_options = array( - 'contain' => array() - ); - - $options = array_merge($default_options, $options); - - $columns = array_keys($this->schema()); - $headers = array(); - foreach($columns as $column){ - $headers[$this->alias][$column] = $column; - } - $data = $this->find('all', $options); - - array_unshift($data, $headers); - return $data; - } - - /** - * Generate a find or the conditions for a find - * based on the search criteria passed into it. - * - * @param array params to search on - * @param array of options - * - order => array of how to order it (Model.created ASC by default) - * - recursive => int of recursive type (0 by default) - * - find => 'all' for find all to be preformed, 'first' for find first to be preformed, false if you just want conditions (false by default) - * - fields => array of fields to select. (* by default) - */ - function search($params = array(), $options = array()){ - $options = array_merge( - array( - 'order' => array("{$this->alias}.created ASC"), - 'recursive' => 0, - 'fields' => array('*'), - 'find' => false, - ), - $options - ); - if(empty($this->_fields)){ - $this->_fields = $this->getColumnTypes(); - } - - //search through params, make sure there is a field that coresponds. - $conditions = array(); - $field_options = array('LIKE','>=','<=','>','<'); - foreach($params as $key => $value){ - if(isset($this->_fields[$key]) && $value){ - if(is_array($value)){ - if(!empty($value['year'])){ - $conditions['AND']["{$this->alias}.$key"] = $value['year'] ."-". $value['month'] . "-" . $value['day']; - } - } else { - $values = explode('[or]', $value); - foreach($values as $value){ - $query_opt = (strpos($value, '%') !== false || strpos($value, '*') !== false) ? ' LIKE' : ''; - if(strpos($value, '*') !== false){ - $value = str_replace('*','%', $value); - } - if(strpos($value, '!') === 0){ - $query_opt = ' !='; - $value = str_replace('!','', $value); - } - if($value == 'null'){ - $value = ''; - } - if(count($values) == 1){ - $conditions['AND']["{$this->alias}.$key$query_opt"] = $value; - } else { - $conditions['AND']['OR'][] = array("{$this->alias}.$key$query_opt" => $value); - } - } - } - } elseif(isset($this->_fields['modified']) && ($key == 'start_date' || $key == 'end_date') && !empty($value['year'])){ - $opt = $key == 'start_date' ? '>=' : '<='; - $conditions['AND']["{$this->alias}.created $opt"] = $params[$key]['year'] ."-". $params[$key]['month'] . "-" . $params[$key]['day']; - } else { - foreach($field_options as $opt){ - if(strpos($key, $opt)){ - $field = substr($key, 0, strlen($key) - (strlen($opt) + 1)); - if(isset($this->_fields[$field]) && $value){ - $conditions['AND']["{$this->alias}.$key"] = $value; - break; - } - } - } - } - } - if($options['find']){ - return $this->find($options['find'], array( - 'conditions' => $conditions, - 'order' => $options['order'], - 'recursive' => $options['recursive'], - 'fields' => $options['fields'], - )); - } else { - return $conditions; - } - } -} \ No newline at end of file From b0231bb56113f4c52cfd51d9b0fed5df89f1d270 Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:38:40 -0200 Subject: [PATCH 05/10] Delete CsvHelper.php --- View/Helpers/CsvHelper.php | 61 -------------------------------------- 1 file changed, 61 deletions(-) delete mode 100755 View/Helpers/CsvHelper.php diff --git a/View/Helpers/CsvHelper.php b/View/Helpers/CsvHelper.php deleted file mode 100755 index 174ed36..0000000 --- a/View/Helpers/CsvHelper.php +++ /dev/null @@ -1,61 +0,0 @@ -clear(); - } - - function clear() { - $this->line = array(); - $this->buffer = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+'); - } - - function addField($value) { - $this->line[] = $value; - } - - function endRow() { - $this->addRow($this->line); - $this->line = array(); - } - - function addRow($row) { - fputcsv($this->buffer, $row, $this->delimiter, $this->enclosure); - } - - function renderHeaders() { - header("Content-type:application/vnd.ms-excel"); - header("Content-disposition:attachment;filename=".$this->filename); - } - - function setFilename($filename) { - $this->filename = $filename; - if (strtolower(substr($this->filename, -4)) != '.csv') { - $this->filename .= '.csv'; - } - } - - function render($outputHeaders = true, $to_encoding = null, $from_encoding = "auto") { - if ($outputHeaders) { - if (is_string($outputHeaders)) { - $this->setFilename($outputHeaders); - } - $this->renderHeaders(); - } - rewind($this->buffer); - $output = stream_get_contents($this->buffer); - if ($to_encoding) { - $output = mb_convert_encoding($output, $to_encoding, $from_encoding); - } - return $this->output($output); - } -} - -?> \ No newline at end of file From 0fb5bd3d13abb4190b5353025183bbd1cca2a0a0 Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:38:51 -0200 Subject: [PATCH 06/10] Delete empty file --- View/Helpers/empty | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 View/Helpers/empty diff --git a/View/Helpers/empty b/View/Helpers/empty deleted file mode 100755 index e69de29..0000000 From 02d1475b1d485a16c6e0211f70731e67d9613d5a Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:39:21 -0200 Subject: [PATCH 07/10] Delete admin_export.ctp --- View/Logs/csv/admin_export.ctp | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 View/Logs/csv/admin_export.ctp diff --git a/View/Logs/csv/admin_export.ctp b/View/Logs/csv/admin_export.ctp deleted file mode 100755 index 8de3378..0000000 --- a/View/Logs/csv/admin_export.ctp +++ /dev/null @@ -1,6 +0,0 @@ -Csv->addRow($row); -} -echo $this->Csv->render($filename); \ No newline at end of file From b9aac9491c04aa9cbe002a0a76d93fb9d6a20fd1 Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:55:00 -0200 Subject: [PATCH 08/10] Update readme.markdown --- readme.markdown | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/readme.markdown b/readme.markdown index d495deb..d90b2ed 100644 --- a/readme.markdown +++ b/readme.markdown @@ -27,6 +27,10 @@ Run the schema into your database: $ cake schema create --plugin DatabaseLog +Load plugin in bootstrap.php + + CakePlugin::load('DatabaseLog'); + ## Setup Create a config file in `app/Config/database_log` with the following (example file in plugin.) @@ -55,4 +59,5 @@ Anywhere in your app where you call log() or CakeLog::write the database logger Navigate to `http://www.example.com/admin/database_log/logs` to view/search/delete your logs. Warning: you should have added admin prefix for routes. -Configure::write('Routing.prefixes', array('admin')); \ No newline at end of file + + Configure::write('Routing.prefixes', array('admin')); From 75c4833490b83e4cb66ad6477b35e74a4af6823b Mon Sep 17 00:00:00 2001 From: "Angelito M. Goulart" Date: Thu, 2 Jan 2014 10:57:29 -0200 Subject: [PATCH 09/10] Delete .DS_Store --- Config/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Config/.DS_Store diff --git a/Config/.DS_Store b/Config/.DS_Store deleted file mode 100644 index aad9ba9345fa40b20ea48d4a14dedf82d8eeaa11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5Z-NTO;8~hL2rxaA}LYo!9yq&JPIlFU_}#COduwuP3@sXBffx-;?wv% z&g^av!FUz1Gcfzj&d+Z4gX|AujQ1B|mobYmW`H7cG-?FhwV{SiM&xpgN9G61`7}tf zpk|=I=)!MrGmqV~h)r1a`#*wd63=tn{^X5jYpcC&n5MBi9>r;xE&JIb4d>Thlr6nD zoCN;tM%uZbFXnxJCL>pV9zjIf!z@d{9_#E;9Olujb+}q}PaUTtoUUDT#H!b`JL1GS zD+<#vOzYj)KRQ0Y9QwucOZln@25^56pop%Bpuy`i##@LeVB=c?QD}5EmI@&P!c{4t zD&_i#!Bsi|F+dDd8EC4mh3EeT{4%wV z{AvmHhyh~YpE1B&18>lWMd`Ek+w$ Date: Thu, 2 Jan 2014 10:57:46 -0200 Subject: [PATCH 10/10] Delete database_logger.php.example --- Config/database_logger.php.example | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 Config/database_logger.php.example diff --git a/Config/database_logger.php.example b/Config/database_logger.php.example deleted file mode 100644 index 6b8baec..0000000 --- a/Config/database_logger.php.example +++ /dev/null @@ -1,12 +0,0 @@ - array( - 'write' => 'default', //DataSource to write to. - 'read' => 'default', //Dadtasource to read from. - ) -);
Paginator->sort('created');?>