BxDolView.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. bx_import('BxDolViewQuery');
  10. define ('BX_DOL_VIEW_OLD_VIEWS', 3 * 86400); ///< views older than this number of seconds will be deleted automatically
  11. /**
  12. * Track any object views automatically
  13. *
  14. * Add record to sys_object_view table to track object views,
  15. * to record view just create this class instance with your object id,
  16. * for example:
  17. * @code
  18. * BxDolView::getObjectInstance('my_system', 25); // 25 - is object id
  19. * @endcode
  20. *
  21. * Description of sys_object_view table fields:
  22. * @code
  23. * `name` - system name, it is better to use unique module prefix here, lowercase and all spaces are underscored
  24. * `table_track` - table to track views
  25. * `period` - period in secs to update next views, default is 86400(1 day)
  26. * `is_on` - is the system activated
  27. * `trigger_table` - table where you need to update views field
  28. * `trigger_field_id` - table field id to unique determine object
  29. * `trigger_field_count` - table field where total view number is stored
  30. * `class_name` - your custom class name, if you overrride default class
  31. * `class_file` - your custom class path
  32. * @endcode
  33. *
  34. * Structure of the track table is the following:
  35. * @code
  36. * CREATE TABLE `my_views_track` (
  37. * `object_id` int(11) NOT NULL default '0', -- this field type must be exact as your object id type
  38. * `viewer_id` int(11) NOT NULL default '0', -- viewer profile id
  39. * `viewer_nip` int(11) unsigned NOT NULL default '0', -- viewer ip address to track guest views
  40. * `date` int(11) NOT NULL default '0', -- timestamp of last recorded view
  41. * KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
  42. * ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  43. * @endcode
  44. *
  45. */
  46. class BxDolView extends BxDol
  47. {
  48. var $_iId = 0; ///< item id to be viewed
  49. var $_sSystem = ''; ///< current view system name
  50. var $_aSystem = array (); ///< current view system array
  51. var $_oQuery = null;
  52. /**
  53. * Constructor
  54. */
  55. function BxDolView($sSystem, $iId, $iInit = 1)
  56. {
  57. parent::__construct();
  58. $this->_aSystems = $this->getSystems();
  59. if(!isset($this->_aSystems[$sSystem]))
  60. return;
  61. $this->_sSystem = $sSystem;
  62. $this->_aSystem = $this->_aSystems[$sSystem];
  63. if(!$this->isEnabled())
  64. return;
  65. $this->_oQuery = new BxDolViewQuery($this);
  66. if($iInit)
  67. $this->init($iId);
  68. }
  69. /**
  70. * get votes object instanse
  71. * @param $sSys view object name
  72. * @param $iId associated content id, where vote is available
  73. * @param $iInit perform initialization
  74. * @return null on error, or ready to use class instance
  75. */
  76. public static function getObjectInstance($sSys, $iId, $isMakeView = true)
  77. {
  78. if(isset($GLOBALS['bxDolClasses']['BxDolView!' . $sSys . $iId]))
  79. return $GLOBALS['bxDolClasses']['BxDolView!' . $sSys . $iId];
  80. $aSystems = self::getSystems();
  81. if(!isset($aSystems[$sSys]))
  82. return null;
  83. bx_import('BxTemplView');
  84. $sClassName = 'BxTemplView';
  85. if(!empty($aSystems[$sSys]['class_name'])) {
  86. $sClassName = $aSystems[$sSys]['class_name'];
  87. if(!empty($aSystems[$sSys]['class_file']))
  88. require_once(BX_DIRECTORY_PATH_ROOT . $aSystems[$sSys]['class_file']);
  89. else
  90. bx_import($sClassName);
  91. }
  92. $o = new $sClassName($sSys, $iId, true);
  93. return ($GLOBALS['bxDolClasses']['BxDolView!' . $sSys . $iId] = $o);
  94. }
  95. public static function &getSystems()
  96. {
  97. if(!isset($GLOBALS['bx_dol_vote_systems']))
  98. $GLOBALS['bx_dol_view_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_view', 'getAllWithKey', '
  99. SELECT
  100. `id` as `id`,
  101. `name` AS `name`,
  102. `table_track` AS `table_track`,
  103. `period` AS `period`,
  104. `is_on` AS `is_on`,
  105. `trigger_table` AS `trigger_table`,
  106. `trigger_field_id` AS `trigger_field_id`,
  107. `trigger_field_count` AS `trigger_field_count`,
  108. `class_name` AS `class_name`,
  109. `class_file` AS `class_file`
  110. FROM `sys_objects_view`', 'name');
  111. return $GLOBALS['bx_dol_view_systems'];
  112. }
  113. /**
  114. * it is called on cron every day or similar period to clean old votes
  115. */
  116. public static function maintenance() {
  117. $iResult = 0;
  118. $oDb = BxDolDb::getInstance();
  119. $aSystems = self::getSystems();
  120. foreach($aSystems as $aSystem) {
  121. if(!$aSystem['is_on'])
  122. continue;
  123. $sQuery = $oDb->prepare("DELETE FROM `{$aSystem['table_track']}` WHERE `date` < (UNIX_TIMESTAMP() - ?)", BX_DOL_VIEW_OLD_VIEWS);
  124. $iDeleted = (int)$oDb->query($sQuery);
  125. if($iDeleted > 0)
  126. $oDb->query("OPTIMIZE TABLE `{$aSystem['table_track']}`");
  127. $iResult += $iDeleted;
  128. }
  129. return $iResult;
  130. }
  131. public function init($iId)
  132. {
  133. if(!$this->isEnabled())
  134. return;
  135. if(empty($this->_iId) && $iId)
  136. $this->setId($iId);
  137. }
  138. public function getSystemId()
  139. {
  140. return $this->_aSystem['id'];
  141. }
  142. public function getSystemName()
  143. {
  144. return $this->_sSystem;
  145. }
  146. public function getSystemInfo()
  147. {
  148. return $this->_aSystem;
  149. }
  150. public function getId()
  151. {
  152. return $this->_iId;
  153. }
  154. public function setId($iId)
  155. {
  156. if($iId == $this->getId())
  157. return;
  158. $this->_iId = $iId;
  159. }
  160. public function isEnabled ()
  161. {
  162. return $this->_aSystem && (int)$this->_aSystem['is_on'] == 1;
  163. }
  164. function doView()
  165. {
  166. if(!$this->isEnabled())
  167. return false;
  168. $iObjectId = $this->getId();
  169. $iAuthorId = $this->_getAuthorId();
  170. $sAuthorIp = $this->_getAuthorIp();
  171. if($this->_oQuery->doView($iObjectId, $iAuthorId, $sAuthorIp)) {
  172. $this->_triggerView();
  173. $oZ = new BxDolAlerts($this->_sSystem, 'view', $iObjectId, $iAuthorId);
  174. $oZ->alert();
  175. return true;
  176. }
  177. return false;
  178. }
  179. function onObjectDelete($iObjectId = 0)
  180. {
  181. $this->_oQuery->deleteObjectViews($iObjectId ? $iObjectId : $this->getId());
  182. }
  183. protected function _getAuthorId ()
  184. {
  185. return isMember() ? bx_get_logged_profile_id() : 0;
  186. }
  187. protected function _getAuthorIp ()
  188. {
  189. return $_SERVER['REMOTE_ADDR'];
  190. }
  191. protected function _triggerView()
  192. {
  193. if(!$this->_aSystem['trigger_table'])
  194. return false;
  195. $iId = $this->getId();
  196. if(!$iId)
  197. return false;
  198. return $this->_oQuery->updateTriggerTable($iId);
  199. }
  200. }
  201. /** @} */