Skip to content

Commit

Permalink
Ability to count guests views of pages. New system setting "tickets.c…
Browse files Browse the repository at this point in the history
…ount_guests".

Version 1.5.0-pl
  • Loading branch information
bezumkin committed Feb 15, 2015
1 parent 852bc60 commit f9ae7fb
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 32 deletions.
2 changes: 1 addition & 1 deletion _build/build.config.php
Expand Up @@ -4,7 +4,7 @@
define('PKG_NAME','Tickets');
define('PKG_NAME_LOWER',strtolower(PKG_NAME));
define('PKG_VERSION','1.5.0');
define('PKG_RELEASE','beta2');
define('PKG_RELEASE','pl');
define('PKG_AUTO_INSTALL', true);


Expand Down
1 change: 1 addition & 0 deletions _build/data/transport.plugins.php
Expand Up @@ -11,6 +11,7 @@
'OnManagerPageInit',
'OnWebPagePrerender',
'OnPageNotFound',
'OnLoadWebDocument',
'OnWebPageComplete',
'OnEmptyTrash',
)
Expand Down
8 changes: 7 additions & 1 deletion _build/data/transport.settings.php
Expand Up @@ -169,7 +169,13 @@
'value' => 0,
'xtype' => 'modx-combo-source',
'area' => 'tickets.main',
)
),

'count_guests' => array(
'xtype' => 'combo-boolean',
'value' => false,
'area' => 'tickets.ticket',
),
);

foreach ($tmp as $k => $v) {
Expand Down
4 changes: 4 additions & 0 deletions _build/resolvers/resolve.tables.php
Expand Up @@ -62,6 +62,10 @@

$manager->addField('TicketFile', 'thumbs');

$manager->addField('TicketView', 'guest_key');
$manager->removeIndex('TicketView', 'PRIMARY');
$manager->addIndex('TicketView', 'unique_key');

$modx->setLogLevel($level);
break;

Expand Down
3 changes: 2 additions & 1 deletion core/components/tickets/docs/changelog.txt
@@ -1,11 +1,12 @@
Changelog for Tickets.

1.5.0 beta2
1.5.0 pl
==========
- Ability to specify multiple previews for uploaded images in media source.
- [#115] Fixed tickets uri generation.
- [#110] Fixed aggregate connection to modUser in TicketComment.
- [#95] Ability to remove user files for members of group "Administrator".
- Ability to count guests views of pages. New system setting "tickets.count_guests".

1.4.2 pl1
==========
Expand Down
25 changes: 25 additions & 0 deletions core/components/tickets/elements/plugins/plugin.tickets.php
Expand Up @@ -82,6 +82,31 @@
break;


case 'OnLoadWebDocument':
$key = 'Tickets_User';
if (!$modx->user->isAuthenticated($modx->context->get('key')) && !$modx->getOption('tickets.count_guests', false)) {
return;
}

if (empty($_COOKIE[$key])) {
if (!empty($_SESSION[$key])) {
$guest_key = $_SESSION[$key];
}
else {
$guest_key = $_SESSION[$key] = md5(rand() . time() . rand());
}
setcookie($key, $guest_key, time() + (86400 * 365), '/');
}
else {
$guest_key = $_COOKIE[$key];
}

if (empty($_SESSION[$key])) {
$_SESSION[$key] = $guest_key;
}
break;


case 'OnWebPageComplete':
/** @var Tickets $Tickets */
$Tickets = $modx->getService('tickets');
Expand Down
Expand Up @@ -45,7 +45,7 @@
$select = array(
'TicketsSection' => !empty($includeContent) ? $modx->getSelectColumns($class, $class) : $modx->getSelectColumns($class, $class, '', array('content'), true)
,'Ticket' => 'COUNT(DISTINCT `Ticket`.`id`) as `tickets`'
,'View' => 'COUNT(DISTINCT `View`.`parent`, `View`.`uid`) as `views`'
,'View' => 'COUNT(`View`.`parent`) as `views`'
//,'Vote' => 'SUM(DISTINCT `Vote`.`value`) as `votes`'
);

Expand Down
27 changes: 16 additions & 11 deletions core/components/tickets/elements/snippets/snippet.get_tickets.php
Expand Up @@ -165,11 +165,11 @@
$additional_fields = $pdoFetch->getObject('Ticket', $row['id'], array(
'leftJoin' => array(
'View' => array('class' => 'TicketView', 'on' => '`Ticket`.`id` = `View`.`parent`'),
'LastView' => array('class' => 'TicketView', 'on' => '`Ticket`.`id` = `LastView`.`parent` AND `LastView`.`uid` = '.$modx->user->id),
'LastView' => array('class' => 'TicketView', 'on' => '`Ticket`.`id` = `LastView`.`parent` AND `LastView`.`uid` != 0 AND `LastView`.`uid` = '.$modx->user->id),
'Thread' => array('class' => 'TicketThread', 'on' => '`Thread`.`resource` = `Ticket`.`id` AND `Thread`.`deleted` = 0'),
),
'select' => array(
'View' => 'COUNT(DISTINCT `View`.`uid`) as `views`',
'View' => 'COUNT(`View`.`parent`) as `views`',
'LastView' => '`LastView`.`timestamp` as `new_comments`',
'Thread' => '`Thread`.`id` as `thread`',
),
Expand All @@ -185,16 +185,21 @@

$row['idx'] = $pdoFetch->idx++;
// Processing new comments
if ($Tickets->authenticated && empty($row['new_comments'])) {
$row['new_comments'] = $row['comments'];
if ($Tickets->authenticated) {
if (!empty($row['new_comments'])) {
$row['new_comments'] = $modx->getCount('TicketComment', array(
'published' => 1,
'thread' => $row['thread'],
'createdon:>' => $row['new_comments'],
'createdby:!=' => $modx->user->id,
));
}
else {
$row['new_comments'] = $row['comments'];
}
}
elseif (!empty($row['new_comments'])) {
$row['new_comments'] = $modx->getCount('TicketComment', array(
'published' => 1,
'thread' => $row['thread'],
'createdon:>' => $row['new_comments'],
'createdby:!=' => $modx->user->id,
));
else {
$row['new_comments'] = '';
}

// Processing chunk
Expand Down
11 changes: 7 additions & 4 deletions core/components/tickets/lexicon/en/setting.inc.php
Expand Up @@ -62,10 +62,13 @@
$_lang['setting_tickets.mail_bcc_level'] = 'Level of admin notifications';
$_lang['setting_tickets.mail_bcc_level_desc'] = 'There are 3 possible levels of admin notifications: 0 - disabled, 1 - send only messages about new tickets, 2 - tickets + comments. Recommended level is 1.';

$_lang['setting_tickets.section_id_as_alias'] = 'Use id of section as alias';
$_lang['setting_tickets.section_id_as_alias_desc'] = 'If true, aliases for friendly urls of sections will don`t be generated. Id will be set as alias.';
$_lang['setting_tickets.ticket_id_as_alias'] = 'Use id of ticket as alias';
$_lang['setting_tickets.ticket_id_as_alias_desc'] = 'If true, aliases for friendly urls of tickets will don`t be generated. Id will be set as alias.';
$_lang['setting_tickets.count_guests'] = 'Count views of pages by guests';
$_lang['setting_tickets.count_guests_desc'] = 'When enabled, component will count views of pages by all users, not just authorized. Keep in mind that with this approach the number of viewings is quite easy to cheat.';

//$_lang['setting_tickets.section_id_as_alias'] = 'Use id of section as alias';
//$_lang['setting_tickets.section_id_as_alias_desc'] = 'If true, aliases for friendly urls of sections will don`t be generated. Id will be set as alias.';
//$_lang['setting_tickets.ticket_id_as_alias'] = 'Use id of ticket as alias';
//$_lang['setting_tickets.ticket_id_as_alias_desc'] = 'If true, aliases for friendly urls of tickets will don`t be generated. Id will be set as alias.';

$_lang['tickets.source_thumbnail_desc'] = 'JSON encoded array of options for generating thumbnail.';
$_lang['tickets.source_maxUploadWidth_desc'] = 'Maximum width of image for upload. All images, that exceeds this parameter, will be resized to fit..';
Expand Down
5 changes: 4 additions & 1 deletion core/components/tickets/lexicon/ru/setting.inc.php
Expand Up @@ -62,6 +62,9 @@
$_lang['setting_tickets.mail_bcc_level'] = 'Уровень уведомления администраторов';
$_lang['setting_tickets.mail_bcc_level_desc'] = 'Возможны 3 уровня уведомлений администраторов: 0 - отключено, 1 - отправлять только сообщения о новых тикетах, 2 - тикеты + комментарии. Рекомендуемый уровень - 1.';

$_lang['setting_tickets.count_guests'] = 'Считать просмотры страниц гостями';
$_lang['setting_tickets.count_guests_desc'] = 'При включении этого параметра учитываются просмотры страниц всеми посетителями сайта, а не только авторизованными. Имейте в виду, что при таком подходе счетчик просмотров довольно легко накрутить.';

//$_lang['setting_tickets.section_id_as_alias'] = 'Id раздела как псевдоним';
//$_lang['setting_tickets.section_id_as_alias_desc'] = 'Если включено, псевдонимы для дружественных имён разделов не будут генерироваться. Вместо этого будут подставляться их id.';
//$_lang['setting_tickets.ticket_id_as_alias'] = 'Id тикета как псевдоним';
Expand All @@ -74,4 +77,4 @@
$_lang['tickets.source_maxUploadWidth_desc'] = 'Максимальная ширина изображения для загрузки. Всё, что больше, будет ужато до этого значения.';
$_lang['tickets.source_maxUploadHeight_desc'] = 'Максимальная высота изображения для загрузки. Всё, что больше, будет ужато до этого значения.';
$_lang['tickets.source_maxUploadSize_desc'] = 'Максимальный размер загружаемых изображений (в байтах).';
$_lang['tickets.source_imageNameType_desc'] = 'Этот параметр указывает, как нужно переименовать файл при загрузке. Hash - это генерация уникального имени, в зависимости от содержимого файла. Friendly - генерация имени по алгоритму дружественных url страниц сайта (они управляются системными настройками).';
$_lang['tickets.source_imageNameType_desc'] = 'Этот параметр указывает, как нужно переименовать файл при загрузке. Hash - это генерация уникального имени, в зависимости от содержимого файла. Friendly - генерация имени по алгоритму дружественных url страниц сайта (они управляются системными настройками).';
24 changes: 20 additions & 4 deletions core/components/tickets/lexicon/uk/setting.inc.php
Expand Up @@ -38,6 +38,10 @@
$_lang['setting_tickets.process_tags_default_desc'] = 'Эта настройка включает или отключает параметр "Выполнять теги MODX" по умолчанию у новых тикетов.';
$_lang['setting_tickets.private_ticket_page'] = 'Редирект с приватных тикетов';
$_lang['setting_tickets.private_ticket_page_desc'] = 'Id существующего ресурса MODX, на который отправлять пользователя, если у него недостаточно прав для просмотра приватного тикета.';
$_lang['setting_tickets.unpublished_ticket_page'] = 'Страница неопубликованных тикетов';
$_lang['setting_tickets.unpublished_ticket_page_desc'] = 'Id существующего ресурса MODX, которая будет показана при запросе неопубликованного тикета.';
$_lang['setting_tickets.ticket_max_cut'] = 'Максимальный размер текста без сut';
$_lang['setting_tickets.ticket_max_cut_desc'] = 'Максимальное количество символов без тегов, которые можно сохранить без тега cut.';


$_lang['setting_tickets.snippet_prepare_comment'] = 'Сниппет обработки комментария';
Expand All @@ -58,7 +62,19 @@
$_lang['setting_tickets.mail_bcc_level'] = 'Уровень уведомления администраторов';
$_lang['setting_tickets.mail_bcc_level_desc'] = 'Возможны 3 уровня уведомлений администраторов: 0 - отключено, 1 - отправлять только сообщения о новых тикетах, 2 - тикеты + комментарии. Рекомендуемый уровень - 1.';

$_lang['setting_tickets.section_id_as_alias'] = 'Id раздела как псевдоним';
$_lang['setting_tickets.section_id_as_alias_desc'] = 'Если включено, псевдонимы для дружественных имён разделов не будут генерироваться. Вместо этого будут подставляться их id.';
$_lang['setting_tickets.ticket_id_as_alias'] = 'Id тикета как псевдоним';
$_lang['setting_tickets.ticket_id_as_alias_desc'] = 'Если включено, псевдонимы для дружественных имён тикетов не будут генерироваться. Вместо этого будут подставляться их id.';
$_lang['setting_tickets.count_guests'] = 'Считать просмотры страниц гостями';
$_lang['setting_tickets.count_guests_desc'] = 'При включении этого параметра учитываются просмотры страниц всеми посетителями сайта, а не только авторизованными. Имейте в виду, что при таком подходе счетчик просмотров довольно легко накрутить.';

//$_lang['setting_tickets.section_id_as_alias'] = 'Id раздела как псевдоним';
//$_lang['setting_tickets.section_id_as_alias_desc'] = 'Если включено, псевдонимы для дружественных имён разделов не будут генерироваться. Вместо этого будут подставляться их id.';
//$_lang['setting_tickets.ticket_id_as_alias'] = 'Id тикета как псевдоним';
//$_lang['setting_tickets.ticket_id_as_alias_desc'] = 'Если включено, псевдонимы для дружественных имён тикетов не будут генерироваться. Вместо этого будут подставляться их id.';

$_lang['setting_tickets.source_default'] = 'Источник медиа для тикетов';
$_lang['setting_tickets.source_default_desc'] = 'Выберите источник медиа, который будет использован по умолчанию для загрузки файлов тикетов.';

$_lang['tickets.source_thumbnail_desc'] = 'Закодированный в JSON массив с параметрами генерации уменьшенной копии изображения.';
$_lang['tickets.source_maxUploadWidth_desc'] = 'Максимальная ширина изображения для загрузки. Всё, что больше, будет ужато до этого значения.';
$_lang['tickets.source_maxUploadHeight_desc'] = 'Максимальная высота изображения для загрузки. Всё, что больше, будет ужато до этого значения.';
$_lang['tickets.source_maxUploadSize_desc'] = 'Максимальный размер загружаемых изображений (в байтах).';
$_lang['tickets.source_imageNameType_desc'] = 'Этот параметр указывает, как нужно переименовать файл при загрузке. Hash - это генерация уникального имени, в зависимости от содержимого файла. Friendly - генерация имени по алгоритму дружественных url страниц сайта (они управляются системными настройками).';
2 changes: 2 additions & 0 deletions core/components/tickets/model/schema/tickets.mysql.schema.xml
Expand Up @@ -161,11 +161,13 @@
<object class="TicketView" table="tickets_views" extends="xPDOObject">
<field key="parent" dbtype="int" precision="10" phptype="integer" attributes="unsigned" null="false" default="0" index="pk" />
<field key="uid" dbtype="int" precision="10" phptype="integer" attributes="unsigned" null="false" default="0" index="pk" />
<field key="guest_key" dbtype="char" precision="32" phptype="string" null="true" default="NULL" index="pk" />
<field key="timestamp" dbtype="datetime" phptype="datetime" null="false" />

<index alias="unique_key" name="unique_key" primary="true" unique="true" type="BTREE">
<column key="parent" length="" collation="A" null="false" />
<column key="uid" length="" collation="A" null="false" />
<column key="guest_key" length="" collation="A" null="false" />
</index>

<aggregate alias="Ticket" class="Ticket" local="parent" foreign="id" cardinality="one" owner="foreign" />
Expand Down
16 changes: 16 additions & 0 deletions core/components/tickets/model/tickets/mysql/ticketview.map.inc.php
Expand Up @@ -8,6 +8,7 @@
array (
'parent' => 0,
'uid' => 0,
'guest_key' => NULL,
'timestamp' => NULL,
),
'fieldMeta' =>
Expand All @@ -32,6 +33,15 @@
'default' => 0,
'index' => 'pk',
),
'guest_key' =>
array (
'dbtype' => 'char',
'precision' => '32',
'phptype' => 'string',
'null' => true,
'default' => NULL,
'index' => 'pk',
),
'timestamp' =>
array (
'dbtype' => 'datetime',
Expand Down Expand Up @@ -61,6 +71,12 @@
'collation' => 'A',
'null' => false,
),
'guest_key' =>
array (
'length' => '',
'collation' => 'A',
'null' => false,
),
),
),
),
Expand Down
33 changes: 25 additions & 8 deletions core/components/tickets/model/tickets/tickets.class.php
Expand Up @@ -612,7 +612,7 @@ public function getNewComments($name) {
return $this->error($this->modx->lexicon('access_denied'));
}
elseif ($thread = $this->modx->getObject('TicketThread', array('name' => $name))) {
if ($view = $this->modx->getObject('TicketView', array('uid' => $this->modx->user->id, 'parent' => $thread->get('resource')))) {
if ($this->authenticated && $view = $this->modx->getObject('TicketView', array('uid' => $this->modx->user->id, 'parent' => $thread->get('resource')))) {
$date = $view->get('timestamp');
$q = $this->modx->newQuery('TicketComment');
$q->leftJoin('modUser', 'User', '`User`.`id` = `TicketComment`.`createdby`');
Expand Down Expand Up @@ -766,7 +766,7 @@ public function templateNode($node = array(), $tpl = null) {

// Checking comment novelty
if (isset($node['resource']) && $this->last_view === 0) {
if ($view = $this->modx->getObject('TicketView', array('parent' => $node['resource'], 'uid' => $this->modx->user->id))) {
if ($this->authenticated && $view = $this->modx->getObject('TicketView', array('parent' => $node['resource'], 'uid' => $this->modx->user->id))) {
$this->last_view = strtotime($view->get('timestamp'));
}
else {
Expand Down Expand Up @@ -1287,13 +1287,30 @@ public function declension($count, $forms, $lang = null) {
* @return void
*/
public function logView($resource) {
if ($this->authenticated && !empty($resource)) {
$table = $this->modx->getTableName('TicketView');
$timestamp = date('Y-m-d H:i:s');
$sql = "INSERT INTO {$table} (`uid`,`parent`,`timestamp`) VALUES ({$this->modx->user->id},{$resource},'{$timestamp}') ON DUPLICATE KEY UPDATE `timestamp` = '{$timestamp}'";
if ($stmt = $this->modx->prepare($sql)) {
$stmt->execute();
$key = 'Tickets_User';
$table = $this->modx->getTableName('TicketView');
$sql = '';

if (!$this->authenticated) {
if (!$this->modx->getOption('tickets.count_guests', false)) {
return;
}
$guest_key = $_SESSION[$key];
}
else {
if (!empty($_SESSION[$key])) {
$sql .= "DELETE FROM {$table} WHERE `uid` = 0 AND `guest_key` = '{$_SESSION[$key]}' AND `parent` = {$resource};";
}
$guest_key = '';
}

$timestamp = date('Y-m-d H:i:s');
$sql .= "INSERT INTO {$table} (`uid`, `guest_key`, `parent`, `timestamp`)
VALUES ({$this->modx->user->id}, '{$guest_key}', {$resource}, '{$timestamp}')
ON DUPLICATE KEY UPDATE `timestamp` = '{$timestamp}'";

if ($stmt = $this->modx->prepare($sql)) {
$stmt->execute();
}
}

Expand Down

0 comments on commit f9ae7fb

Please sign in to comment.