BxDolViews.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup DolphinCore Dolphin Core
  7. * @{
  8. */
  9. define ('BX_OLD_VIEWS', 3*86400); ///< views older than this number of seconds will be deleted automatically
  10. /**
  11. * @page objects
  12. * @section views_counter Views Counter
  13. * @ref BxDolViews
  14. */
  15. /**
  16. * Track any object views automatically
  17. *
  18. * Add record to sys_object_views table to track object views,
  19. * to record view just create this class instance with your object id,
  20. * for example:
  21. * @code
  22. * new BxDolViews('my_system', 25); // 25 - is object id
  23. * @endcode
  24. *
  25. * Description of sys_object_views table fields:
  26. * @code
  27. * `name` - system name, it is better to use unique module prefix here, lowercase and all spaces are underscored
  28. * `table_track` - table to track views
  29. * `period` - period in secs to update next views, default is 86400(1 day)
  30. * `trigger_table` - table where you need to update views field
  31. * `trigger_field_id` - table field id to unique determine object
  32. * `trigger_field_views` - table field where total view number is stored
  33. * `is_on` - is the system activated
  34. * @endcode
  35. *
  36. * Structure of the track table is the following:
  37. * @code
  38. * CREATE TABLE `my_views_track` (
  39. * `id`, -- this field type must be exact as your object id type
  40. * `viewer` int(10) unsigned NOT NULL, -- viewer profile id
  41. * `ip` int(10) unsigned NOT NULL, -- viewer ip address to track guest views
  42. * `ts` int(10) unsigned NOT NULL, -- timestamp of last recorded view
  43. * KEY `id` (`id`,`viewer`,`ip`)
  44. * ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  45. * @endcode
  46. *
  47. */
  48. class BxDolViews extends BxDol
  49. {
  50. var $_iId = 0; ///< item id to be viewed
  51. var $_sSystem = ''; ///< current view system name
  52. var $_aSystem = array (); ///< current view system array
  53. /**
  54. * Constructor
  55. */
  56. function BxDolViews($sSystem, $iId, $isMakeView = true)
  57. {
  58. $aSystems = $this->getAllSystems ();
  59. if (!isset($aSystems[$sSystem]))
  60. return;
  61. $this->_aSystem = $aSystems[$sSystem];
  62. $this->_sSystem = $sSystem;
  63. if (!$this->isEnabled())
  64. return;
  65. $this->_iId = $iId;
  66. if ($isMakeView)
  67. $this->makeView();
  68. }
  69. function makeView ()
  70. {
  71. if (!$this->isEnabled()) return false;
  72. $oDb = BxDolDb::getInstance();
  73. $iMemberId = getLoggedId();
  74. $sIp = $_SERVER['REMOTE_ADDR'];
  75. $iTime = time();
  76. if ($iMemberId)
  77. $sWhere = $oDb->prepare(" AND `viewer` = ? ", $iMemberId);
  78. else
  79. $sWhere = $oDb->prepare(" AND `viewer` = '0' AND `ip` = INET_ATON(?) ", $sIp);
  80. $sQuery = $oDb->prepare("SELECT `ts` FROM `{$this->_aSystem['table_track']}` WHERE `id` = ? $sWhere", $this->getId());
  81. $iTs = (int)($oDb->getOne($sQuery));
  82. $iRet = 0;
  83. if (!$iTs) {
  84. $sQuery = $oDb->prepare("INSERT IGNORE INTO `{$this->_aSystem['table_track']}` SET `id` = ?, `viewer` = ?, `ip` = INET_ATON(?), `ts` = ?", $this->getId(), $iMemberId, $sIp, $iTime);
  85. $iRet = $oDb->query($sQuery);
  86. } elseif (($iTime - $iTs) > $this->_aSystem['period']) {
  87. $sQuery = $oDb->prepare("UPDATE `{$this->_aSystem['table_track']}` SET `ts` = ? WHERE `id` = ? AND `viewer` = ? AND `ip` = INET_ATON(?)", $iTime, $this->getId(), $iMemberId, $sIp);
  88. $iRet = $oDb->query($sQuery);
  89. }
  90. if ($iRet) {
  91. $this->_triggerView();
  92. $oZ = new BxDolAlerts($this->_sSystem, 'view', $this->getId(), $iMemberId);
  93. $oZ->alert();
  94. return true;
  95. }
  96. return false;
  97. }
  98. function getId ()
  99. {
  100. return $this->_iId;
  101. }
  102. function isEnabled ()
  103. {
  104. return $this->_aSystem && $this->_aSystem['is_on'];
  105. }
  106. function getSystemName()
  107. {
  108. return $this->_sSystem;
  109. }
  110. function getAllSystems () {
  111. $oDb = BxDolDb::getInstance();
  112. return $oDb->fromCache('sys_objects_views', 'getAllWithKey', 'SELECT * FROM `sys_objects_views`', 'name');
  113. }
  114. /**
  115. * call this function when associated object is deleted
  116. */
  117. function onObjectDelete ($iId = 0)
  118. {
  119. $iId = (int) $iId;
  120. $oDb = BxDolDb::getInstance();
  121. $sQuery = $oDb->prepare("DELETE FROM `{$this->_aSystem['table_track']}` WHERE `id` = ?", $iId ? $iId : $this->getId());
  122. $oDb->query($sQuery);
  123. $oDb->query("OPTIMIZE TABLE `{$this->_aSystem['table_track']}`");
  124. }
  125. /**
  126. * it is called on cron every day or similar period
  127. */
  128. function maintenance () {
  129. $oDb = BxDolDb::getInstance();
  130. $iTime = time() - BX_OLD_VIEWS;
  131. $aSystems = $this->getAllSystems ();
  132. $iDeletedRecords = 0;
  133. foreach ($aSystems as $aSystem) {
  134. if (!$aSystem['is_on'])
  135. continue;
  136. $sQuery = $oDb->prepare("DELETE FROM `{$aSystem['table_track']}` WHERE `ts` < ?", $iTime);
  137. $iCount = $oDb->query($sQuery);
  138. if ($iCount)
  139. $oDb->query("OPTIMIZE TABLE `{$aSystem['table_track']}`");
  140. $iDeletedRecords += $iCount;
  141. }
  142. return $iDeletedRecords;
  143. }
  144. function _triggerView() {
  145. $oDb = BxDolDb::getInstance();
  146. $sQuery = $oDb->prepare("UPDATE `{$this->_aSystem['trigger_table']}` SET `{$this->_aSystem['trigger_field_views']}` = `{$this->_aSystem['trigger_field_views']}` + 1 WHERE `{$this->_aSystem['trigger_field_id']}` = ?", $this->getId());
  147. return $oDb->query($sQuery);
  148. }
  149. }
  150. /** @} */