diff --git a/assets/tracker.dashboard.css b/assets/tracker.dashboard.css
index a75be9e..74dbeac 100644
--- a/assets/tracker.dashboard.css
+++ b/assets/tracker.dashboard.css
@@ -1,12 +1,7 @@
-div#dashboard .tracker_log table {
- width: 100%;
+.tracker_activity .panel-inner {
+ padding: 0;
}
-div#dashboard .tracker_log table th,
-div#dashboard .tracker_log table td {
- padding: 1px 10px 1px 0;
+.tracker_activity table {
+ border: none;
}
-
-div#dashboard .tracker_log table th {
- text-align: left;
-}
\ No newline at end of file
diff --git a/content/content.index.php b/content/content.index.php
index 8e564bf..a874043 100644
--- a/content/content.index.php
+++ b/content/content.index.php
@@ -19,7 +19,14 @@ public function view()
// Add a button to clear all activity, if developer
if (Tracker::Author()->isDeveloper()) {
$clearform = Widget::Form(Symphony::Engine()->getCurrentPageURL(), 'post');
- $button = new XMLElement('button', __('Clear All'));
+ Widget::registerSVGIcon(
+ 'close',
+ ''
+ );
+ $button = new XMLElement(
+ 'button',
+ Widget::SVGIcon('close') . '' . __('Clear All') . ''
+ );
$button->setAttributeArray(array('name' => 'action[clear-all]', 'class' => 'button confirm delete', 'title' => __('Clear all activity'), 'accesskey' => 'd', 'data-message' => __('Are you sure you want to clear all activity?')));
$clearform->appendChild($button);
@@ -42,13 +49,9 @@ public function view()
$filters = array();
if (isset($_REQUEST['filter'])) {
-
- list($column, $value) = explode(':', $_REQUEST['filter'], 2);
- $values = explode(',', $value);
- $filters[$column] = array();
-
- foreach ($values as $value) {
- $filters[$column][] = rawurldecode($value);
+ foreach (explode('-', $_REQUEST['filter']) as $key => $value) {
+ $filter = explode(':', $value);
+ $filters[$filter[0]] = explode(',', rawurldecode($filter[1]));
}
}
@@ -112,10 +115,12 @@ public function view()
// Assemble the columns
$col_date = Widget::TableData($date);
+ $col_date->setAttribute('data-title', __('Date'));
$col_time = Widget::TableData($time);
+ $col_time->setAttribute('data-title', __('Time'));
$col_desc = Widget::TableData($description, $description_class);
-
$col_desc->appendChild(Widget::Input("items[{$activity['id']}]", null, 'checkbox'));
+ $col_desc->setAttribute('data-title', __('Activity'));
// Insert the row
$tbody[] = Widget::TableRow(array($col_desc, $col_date, $col_time), $row_class, 'activity-' . $activity['id']);
@@ -145,13 +150,17 @@ public function view()
// Append pagination
$filter_sql = Tracker::buildFilterSQL($filters);
- $sql = '
- SELECT count(id) as `count`
- FROM `tbl_tracker_activity`' .
- $filter_sql
- ;
$per_page = Symphony::Configuration()->get('pagination_maximum_rows', 'symphony');
- $total_entries = Symphony::Database()->fetchVar('count', 0, $sql);
+ $q = Symphony::Database()
+ ->select(['count(id)' => 'count'])
+ ->from('tbl_tracker_activity');
+ foreach ($filter_sql as $key => $value) {
+ $q->where([$key => $value]);
+ }
+ $total_entries = $q
+ ->execute()
+ ->variable('count');
+
$remaining_entries = max(0, $total_entries - ($start + $per_page));
$total_pages = max(1, ceil($total_entries * (1 / $per_page)));
$remaining_pages = max(0, $total_pages - $current_page);
@@ -204,16 +213,24 @@ public function __actionIndex()
$checked = @array_keys($_POST['items']);
if (@array_key_exists('clear-all', $_POST['action'])) {
- $sql = 'TRUNCATE `tbl_tracker_activity`;';
- Symphony::Database()->query($sql);
+ // $sql = 'TRUNCATE `tbl_tracker_activity`;';
+ // Symphony::Database()->query($sql);
+ Symphony::Database()
+ ->truncate('tbl_tracker_activity')
+ ->execute()
+ ->success();
+
redirect(Administration::instance()->getCurrentPageURL());
} elseif (is_array($checked) && !empty($checked)) {
switch ($_POST['with-selected']) {
case 'delete':
-
- Symphony::Database()->delete('tbl_tracker_activity', ' `id` IN("' . implode('","',$checked) . '")');
+ Symphony::Database()
+ ->delete('tbl_tracker_activity')
+ ->where(['id' => ['in' => $checked]])
+ ->execute()
+ ->success();
redirect(Administration::instance()->getCurrentPageURL());
break;
diff --git a/data-sources/data.tracker_activity.php b/data-sources/data.tracker_activity.php
index 318334c..98f43d1 100644
--- a/data-sources/data.tracker_activity.php
+++ b/data-sources/data.tracker_activity.php
@@ -87,7 +87,7 @@ public function execute(array &$param_pool = null)
);
// Build the element
- $item = new XMLElement('activity', NULL, array(
+ $item = new XMLElement('activity', null, array(
'type' => $activity['action_type'],
'entry-id' => $activity['item_id']
));
diff --git a/extension.driver.php b/extension.driver.php
index 7f5474d..369d990 100644
--- a/extension.driver.php
+++ b/extension.driver.php
@@ -261,20 +261,33 @@ public function getSubscribedDelegates()
public function install()
{
- Symphony::Database()->query(
- "CREATE TABLE IF NOT EXISTS `tbl_tracker_activity` (
- `id` int(11) unsigned NOT NULL auto_increment,
- `item_type` varchar(255),
- `item_id` varchar(75),
- `action_type` varchar(255),
- `user_id` int(11),
- `timestamp` timestamp,
- `fallback_username` varchar(2048),
- `fallback_description` varchar(2048),
- PRIMARY KEY (`id`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
-
- return true;
+ return Symphony::Database()
+ ->create('tbl_tracker_activity')
+ ->ifNotExists()
+ ->fields([
+ 'id' => [
+ 'type' => 'int(11)',
+ 'auto' => true,
+ ],
+ 'item_type' => 'varchar(255)',
+ 'item_id' => [
+ 'type' => 'varchar(75)',
+ 'null' => true,
+ ],
+ 'action_type' => 'varchar(255)',
+ 'user_id' => [
+ 'type' => 'int(11)',
+ 'null' => true,
+ ],
+ 'timestamp' => 'timestamp',
+ 'fallback_username' => 'varchar(2048)',
+ 'fallback_description' => 'varchar(2048)',
+ ])
+ ->keys([
+ 'id' => 'primary',
+ ])
+ ->execute()
+ ->success();
}
public function update($previousVersion = null)
@@ -287,11 +300,14 @@ public function update($previousVersion = null)
// less than 1.7.0
if ($ret && version_compare($previousVersion, '1.7.0', '<')) {
- $ret = Symphony::Database()->query("
- ALTER TABLE `tbl_tracker_activity`
- MODIFY `fallback_username` varchar(2048),
- MODIFY `fallback_description` varchar(2048);
- ");
+ $ret = Symphony::Database()
+ ->alter('tbl_tracker_activity')
+ ->modify([
+ 'fallback_username' => 'varchar(2048)',
+ 'fallback_description' => 'varchar(2048)',
+ ])
+ ->execute()
+ ->success();
}
return $ret;
@@ -299,9 +315,12 @@ public function update($previousVersion = null)
public function uninstall()
{
- Symphony::Database()->query(
- "DROP TABLE IF EXISTS `tbl_tracker_activity`;"
- );
+ Symphony::Database()
+ ->drop('tbl_tracker_activity')
+ ->ifExists()
+ ->execute()
+ ->success();
+
Symphony::Configuration()->remove('tracker');
return Symphony::Configuration()->write();
@@ -806,7 +825,10 @@ public function appendPreferences($context)
$sm = new SectionManager(Administration::instance());
- $sections = $sm->fetch();
+ $sections = $sm
+ ->select()
+ ->execute()
+ ->rows();
$excluded_sections = explode(',', Symphony::Configuration()->get('excluded-sections', 'tracker'));
if (!empty($sections) && is_array($sections)) {
@@ -834,7 +856,10 @@ public function appendPreferences($context)
$options = array();
$am = new AuthorManager(Administration::instance());
- $authors = $am->fetch();
+ $authors = $am
+ ->select()
+ ->execute()
+ ->rows();
$excluded_authors = explode(',',Symphony::Configuration()->get('excluded-users', 'tracker'));
if (!empty($authors) && is_array($authors)) {
@@ -944,7 +969,7 @@ public function renderPanel($context)
// Check to see we are being called in the right context
// Dashboard also has `contentExtensionDashboardPanel_Config` which extends `AjaxPage`
if (method_exists($page, 'addStylesheetToHead')) {
- $page->addStylesheetToHead(URL . '/extensions/tracker/assets/dashboard.css', 'screen', 151);
+ $page->addStylesheetToHead(URL . '/extensions/tracker/assets/tracker.dashboard.css', 'screen', 151);
}
$logs = Tracker::fetchActivities($filters, (int) $config['limit'], 0);
@@ -989,12 +1014,15 @@ public function renderPanel($context)
// Assemble the columns
$col_date = Widget::TableData($date);
+ $col_date->setAttribute('data-title', __('Activity'));
$col_time = Widget::TableData($time);
+ $col_time->setAttribute('data-title', __('Date'));
$col_desc = Widget::TableData($description);
+ $col_desc->setAttribute('data-title', __('Time'));
// Insert the row
if (!is_null($description)) {
- $tbody[] = Widget::TableRow(array($col_desc, $col_date, $col_time), ($bOdd ? 'odd' : null));
+ $tbody[] = Widget::TableRow(array($col_desc, $col_date, $col_time));
$bOdd = !$bOdd;
}
diff --git a/extension.meta.xml b/extension.meta.xml
index da0e9c7..86047fd 100644
--- a/extension.meta.xml
+++ b/extension.meta.xml
@@ -1,6 +1,6 @@
- Tracker
+ Tracker Activity
Track user and system activity
https://github.com/symphonists/tracker
https://github.com/symphonists/tracker/issues
@@ -18,6 +18,11 @@
+
+ - Update for Symphony 4.x
+ - Code refactoring for Database and EQFA
+ - Replace deprecated method fetch() by select()
+
- Set Author Id to 0 if no author is set (#42)
diff --git a/lib/class.tracker.php b/lib/class.tracker.php
index 44ac872..c009de6 100644
--- a/lib/class.tracker.php
+++ b/lib/class.tracker.php
@@ -87,7 +87,12 @@ public static function getMemberUsername($member)
}
else if (!empty($member['section-id']) && !empty($member['id'])) {
$sectionID = $member['section-id'] ? $member['section-id'] : extension_Members::getMembersSection();
- $sectionHandle = SectionManager::fetch($sectionID)->get('handle');
+ $sectionHandle = (new SectionManager)
+ ->select()
+ ->section($sectionID)
+ ->execute()
+ ->next()
+ ->get('handle');
$link = SYMPHONY_URL . '/publish/' . $sectionHandle . '/edit/' . $member['id'] . '/';
$name = $member['username'] ? $member['username'] : $member['email'];
@@ -113,24 +118,29 @@ public static function truncateValue($value, $max = 2048)
return $value;
}
- public static function fetchActivities(array $filters,$limit = null, $start = 0, $sort = 'timestamp', $order = 'DESC')
+ public static function fetchActivities($filters = array(),$limit = null, $start = 0, $sort = 'timestamp', $order = 'DESC')
{
// Build the filter SQL.
$filter_sql = static::buildFilterSQL($filters);
// Run the query.
- $activities = Symphony::Database()->fetch('
- SELECT
- *
- FROM
- `tbl_tracker_activity`' .
- $filter_sql .
- ' ORDER BY `' .
- $sort . '` ' . $order
- . ($limit ? ' LIMIT ' . intval($start) . ', ' . intval($limit) : '')
- );
+ $q = Symphony::Database()
+ ->select(['*'])
+ ->from('tbl_tracker_activity');
+
+ foreach ($filter_sql as $key => $value) {
+ $q->where([$key => $value]);
+ }
+
+ $q->orderBy($sort, $order);
+
+ if ($limit !== null) {
+ $q->limit(intval($limit));
+ }
- return $activities;
+ return $q
+ ->execute()
+ ->rows();
}
/**
@@ -160,54 +170,41 @@ public static function fetchActivities(array $filters,$limit = null, $start = 0,
* );
*
*/
- public static function buildFilterSQL($filters)
+ public static function buildFilterSQL($filters = array())
{
- $columns = Symphony::Database()->fetch('DESCRIBE `tbl_tracker_activity`');
+ $columns = Symphony::Database()
+ ->describe('tbl_tracker_activity')
+ ->execute()
+ ->rows();
+
foreach($columns as $key => $column) {
$columns[$key] = $column['Field'];
}
- $filter_sql = '';
+ $filter_sql = array();
// If we've got a $filters array, let's build the SQL
- // TODO: I imagine this can be made more elegant
if (!empty($filters) && is_array($filters)) {
- $filter_sql .= ' WHERE ';
- $i = 0;
// Iterate over the field filters
foreach($filters as $field => $options) {
-
// Prevent fatal error when filter field doesn't exist
- if (!in_array($field,$columns)) { return; }
-
- // If there's more than one field filter
- if ($i > 0) {
- $filter_sql .= ' AND ';
+ if (!in_array($field, $columns)) {
+ return array();
}
- // Allow custom SQL by passing a string
- // TODO: Is this a security concern?
- if (!is_array($options)) {
- $filter_sql .= '`' . $field . '` ' . $options . ' ';
+ if (count($options) < 2) {
+ $filter_sql[$field] = $options[0];
}
-
- // Iterate over the filter values and group them with OR
else {
- foreach($options as $num => $option) {
- if ($num == 0 && count($options) > 1) {
- $filter_sql .= ' (';
- }
- if ($num > 0) {
- $filter_sql .= ' OR ';
- }
- $filter_sql .= '`' . $field . '` = "' . $option . '"';
- if (count($options) > 1 && $option == end($options)) {
- $filter_sql .= ')';
- }
+ $opts = array();
+
+ foreach($options as $option) {
+ $opts[] = [$field => $option];
}
+
+ $filter_sql['or'] = $opts;
}
- $i++;
}
}
@@ -318,9 +315,19 @@ public static function getDescription(array $activity)
public static function formatEntryItem($activity, $fallback = false)
{
// Fetch the entry and its section
- $entry = EntryManager::fetch($activity['item_id']);
- $entry = $entry[0];
- $section = SectionManager::fetch($activity['item_type']);
+ $entry = (new EntryManager)
+ ->select()
+ ->entry($activity['item_id'])
+ ->section($activity['item_type'])
+ ->includeAllFields()
+ ->execute()
+ ->next();
+
+ $section = (new SectionManager)
+ ->select()
+ ->section($activity['item_type'])
+ ->execute()
+ ->next();
// If the entry no longer exists, get the fallback entry description
if (!($entry instanceof Entry) || !($section instanceof Section)) {
@@ -521,7 +528,11 @@ public static function formatElementItem($activity, $fallback = false)
case "sections":
// Grab the section info
- $section = SectionManager::fetch($activity['item_id']);
+ $section = (new SectionManager)
+ ->select()
+ ->section($activity['item_id'])
+ ->execute()
+ ->next();
// If the section no longer exists, use the fallback description
if (!($section instanceof Section)) {
@@ -608,7 +619,7 @@ public static function formatElementItem($activity, $fallback = false)
$about = ExtensionManager::about($activity['item_id']);
}
catch (Exception $e) {
- $about = NULL;
+ $about = null;
}
if (empty($about)) {
$item = $activity['fallback_description'];
@@ -652,7 +663,7 @@ public static function formatElementItem($activity, $fallback = false)
break;
default:
- $item = NULL;
+ $item = null;
break;
}