activityReport/inc/class.activity.report.php

774 lines
25 KiB
PHP
Raw Normal View History

<?php
2021-09-02 22:18:08 +00:00
/**
* @brief activityReport, a plugin for Dotclear 2
2022-11-18 20:24:30 +00:00
*
2021-09-02 22:18:08 +00:00
* @package Dotclear
* @subpackage Plugin
2022-11-18 20:24:30 +00:00
*
2021-09-02 22:18:08 +00:00
* @author Jean-Christian Denis and contributors
2022-11-18 20:24:30 +00:00
*
2021-09-02 22:18:08 +00:00
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
2022-11-18 20:24:30 +00:00
if (!defined('DC_RC_PATH')) {
return;
}
class activityReport
{
2021-09-02 22:18:08 +00:00
public $con;
2022-12-15 23:32:15 +00:00
private $ns = null;
2022-11-18 20:24:30 +00:00
private $_global = 0;
private $blog = null;
private $groups = [];
private $settings = [];
private $lock_blog = null;
2021-09-02 22:18:08 +00:00
private $lock_global = null;
2022-12-15 23:32:15 +00:00
public function __construct($ns = null)
2021-09-02 22:18:08 +00:00
{
2022-11-30 21:41:32 +00:00
$this->con = dcCore::app()->con;
$this->blog = dcCore::app()->con->escape(dcCore::app()->blog->id);
2022-12-15 23:32:15 +00:00
$this->ns = dcCore::app()->con->escape($ns ?? basename(dirname(__DIR__)));
2021-09-02 22:18:08 +00:00
$this->getSettings();
# Check if some logs are too olds
$this->obsoleteLogs();
}
public function setGlobal()
{
$this->_global = 1;
}
public function unsetGlobal()
{
$this->_global = 0;
}
2021-09-03 07:45:21 +00:00
public function getGroups($group = null, $action = null)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
if ($action !== null) {
2022-11-18 20:24:30 +00:00
return $this->groups[$group]['actions'][$action] ?? null;
2021-09-03 07:45:21 +00:00
} elseif ($group !== null) {
2022-11-18 20:24:30 +00:00
return $this->groups[$group] ?? null;
2021-09-02 22:18:08 +00:00
}
2022-11-18 20:24:30 +00:00
return $this->groups;
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
public function addGroup($group, $title)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
$this->groups[$group] = [
2022-11-18 20:24:30 +00:00
'title' => $title,
'actions' => [],
2021-09-03 07:45:21 +00:00
];
2022-11-18 20:24:30 +00:00
2021-09-02 22:18:08 +00:00
return true;
}
2021-09-03 07:45:21 +00:00
public function addAction($group, $action, $title, $msg, $behavior, $function)
2021-09-02 22:18:08 +00:00
{
2022-11-18 20:24:30 +00:00
if (!isset($this->groups[$group])) {
return false;
}
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
$this->groups[$group]['actions'][$action] = [
2021-09-02 22:18:08 +00:00
'title' => $title,
2022-11-18 20:24:30 +00:00
'msg' => $msg,
2021-09-03 07:45:21 +00:00
];
2022-11-18 20:24:30 +00:00
dcCore::app()->addBehavior($behavior, $function);
2021-09-02 22:18:08 +00:00
return true;
}
private function getSettings()
{
2021-09-03 07:45:21 +00:00
$settings = [
2022-11-18 20:24:30 +00:00
'active' => false,
'obsolete' => 2419200,
'interval' => 86400,
'lastreport' => 0,
2021-09-03 07:45:21 +00:00
'mailinglist' => [],
2022-11-18 20:24:30 +00:00
'mailformat' => 'plain',
'dateformat' => '%Y-%m-%d %H:%M:%S',
'requests' => [],
'blogs' => [],
2021-09-03 07:45:21 +00:00
];
2021-09-02 22:18:08 +00:00
$this->settings[0] = $this->settings[1] = $settings;
$rs = $this->con->select(
2021-09-03 07:45:21 +00:00
'SELECT setting_id, setting_value, blog_id ' .
2022-11-30 21:35:28 +00:00
'FROM ' . dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME . ' ' .
2021-09-03 07:45:21 +00:00
"WHERE setting_type='" . $this->ns . "' " .
"AND (blog_id='" . $this->blog . "' OR blog_id IS NULL) " .
2021-09-02 22:18:08 +00:00
'ORDER BY setting_id DESC '
);
2022-11-18 20:24:30 +00:00
while ($rs->fetch()) {
2021-09-02 22:18:08 +00:00
$k = $rs->f('setting_id');
$v = $rs->f('setting_value');
$b = $rs->f('blog_id');
$g = $b === null ? 1 : 0;
2021-09-03 07:45:21 +00:00
if (isset($settings[$k])) {
2021-09-02 22:18:08 +00:00
$this->settings[$g][$k] = self::decode($v);
}
}
# Force blog
2022-11-27 21:19:52 +00:00
$this->settings[0]['blogs'] = [0 => $this->blog];
2021-09-02 22:18:08 +00:00
}
public function getSetting($n)
{
2021-09-03 07:45:21 +00:00
return $this->settings[$this->_global][$n] ?? null;
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
public function setSetting($n, $v)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
if (!isset($this->settings[$this->_global][$n])) {
return null;
}
2021-09-02 22:18:08 +00:00
$c = $this->delSetting($n);
2022-11-30 21:35:28 +00:00
$cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME);
$this->con->writeLock(dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME);
2021-09-02 22:18:08 +00:00
2022-11-18 20:24:30 +00:00
$cur->blog_id = $this->_global ? null : $this->blog;
$cur->setting_id = $this->con->escape($n);
$cur->setting_type = $this->ns;
2021-09-02 22:18:08 +00:00
$cur->setting_value = (string) self::encode($v);
$cur->insert();
$this->con->unlock();
$this->settings[$this->_global][$n] = $v;
return true;
}
private function delSetting($n)
{
return $this->con->execute(
2022-11-30 21:35:28 +00:00
'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME . ' ' .
2022-11-18 20:24:30 +00:00
'WHERE blog_id' . ($this->_global ? ' IS NULL' : "='" . $this->blog . "'") . ' ' .
2021-09-03 07:45:21 +00:00
"AND setting_id='" . $this->con->escape($n) . "' " .
"AND setting_type='" . $this->ns . "' "
2021-09-02 22:18:08 +00:00
);
}
2021-09-03 07:45:21 +00:00
// Action params to put in params['sql']
2021-09-02 22:18:08 +00:00
public static function requests2params($requests)
{
2021-09-03 07:45:21 +00:00
$r = [];
2022-11-18 20:24:30 +00:00
foreach ($requests as $group => $actions) {
foreach ($actions as $action => $is) {
$r[] = "activity_group='" . $group . "' AND activity_action='" . $action . "' ";
2021-09-02 22:18:08 +00:00
}
}
2022-11-18 20:24:30 +00:00
2021-09-03 07:45:21 +00:00
return empty($r) ? '' : 'AND (' . implode('OR ', $r) . ') ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
public function getLogs($p, $count_only = false)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
if ($count_only) {
2021-09-02 22:18:08 +00:00
$r = 'SELECT count(E.activity_id) ';
2021-09-03 07:45:21 +00:00
} else {
2021-09-02 22:18:08 +00:00
$content_r = empty($p['no_content']) ? 'activity_logs, ' : '';
2022-11-18 20:24:30 +00:00
if (!empty($p['columns']) && is_array($p['columns'])) {
$content_r .= implode(', ', $p['columns']) . ', ';
2021-09-02 22:18:08 +00:00
}
2022-11-18 20:24:30 +00:00
$r = 'SELECT E.activity_id, E.blog_id, B.blog_url, B.blog_name, ' . $content_r .
2021-09-03 07:45:21 +00:00
'E.activity_group, E.activity_action, E.activity_dt, ' .
2021-09-02 22:18:08 +00:00
'E.activity_blog_status, E.activity_super_status ';
}
2022-11-30 21:35:28 +00:00
$r .= 'FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' E ' .
'LEFT JOIN ' . dcCore::app()->prefix . dcBlog::BLOG_TABLE_NAME . ' B on E.blog_id=B.blog_id ';
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
if (!empty($p['from'])) {
$r .= $p['from'] . ' ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if ($this->_global) {
2022-11-18 20:24:30 +00:00
$r .= 'WHERE E.activity_super_status = 0 ';
2021-09-03 07:45:21 +00:00
} else {
2022-11-18 20:24:30 +00:00
$r .= 'WHERE E.activity_blog_status = 0 ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (!empty($p['activity_type'])) {
$r .= "AND E.activity_type = '" . $this->con->escape($p['activity_type']) . "' ";
} else {
$r .= "AND E.activity_type = '" . $this->ns . "' ";
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (!empty($p['blog_id'])) {
2022-11-18 20:24:30 +00:00
if (is_array($p['blog_id'])) {
2021-09-03 07:45:21 +00:00
$r .= 'AND E.blog_id' . $this->con->in($p['blog_id']);
} else {
$r .= "AND E.blog_id = '" . $this->con->escape($p['blog_id']) . "' ";
2021-09-02 22:18:08 +00:00
}
2022-11-18 20:24:30 +00:00
} elseif ($this->_global) {
2021-09-02 22:18:08 +00:00
$r .= 'AND E.blog_id IS NOT NULL ';
2021-09-03 07:45:21 +00:00
} else {
$r .= "AND E.blog_id='" . $this->blog . "' ";
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (isset($p['activity_group'])) {
if (is_array($p['activity_group']) && !empty($p['activity_group'])) {
$r .= 'AND E.activity_group ' . $this->con->in($p['activity_group']);
} elseif ($p['activity_group'] != '') {
$r .= "AND E.activity_group = '" . $this->con->escape($p['activity_group']) . "' ";
2021-09-02 22:18:08 +00:00
}
}
2021-09-03 07:45:21 +00:00
if (isset($p['activity_action'])) {
if (is_array($p['activity_action']) && !empty($p['activity_action'])) {
$r .= 'AND E.activity_action ' . $this->con->in($p['activity_action']);
} elseif ($p['activity_action'] != '') {
$r .= "AND E.activity_action = '" . $this->con->escape($p['activity_action']) . "' ";
2021-09-02 22:18:08 +00:00
}
}
2021-09-03 07:45:21 +00:00
if (isset($p['activity_blog_status'])) {
2022-11-18 20:24:30 +00:00
$r .= 'AND E.activity_blog_status = ' . ((int) $p['activity_blog_status']) . ' ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (isset($p['activity_super_status'])) {
2022-11-18 20:24:30 +00:00
$r .= 'AND E.activity_super_status = ' . ((int) $p['activity_super_status']) . ' ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (isset($p['from_date_ts'])) {
2022-11-18 20:24:30 +00:00
$dt = date('Y-m-d H:i:s', $p['from_date_ts']);
2021-09-03 07:45:21 +00:00
$r .= "AND E.activity_dt >= TIMESTAMP '" . $dt . "' ";
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (isset($p['to_date_ts'])) {
2022-11-18 20:24:30 +00:00
$dt = date('Y-m-d H:i:s', $p['to_date_ts']);
2021-09-03 07:45:21 +00:00
$r .= "AND E.activity_dt < TIMESTAMP '" . $dt . "' ";
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (!empty($p['sql'])) {
$r .= $p['sql'] . ' ';
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if (!$count_only) {
if (!empty($p['order'])) {
$r .= 'ORDER BY ' . $this->con->escape($p['order']) . ' ';
2021-09-02 22:18:08 +00:00
} else {
$r .= 'ORDER BY E.activity_dt DESC ';
}
}
2021-09-03 07:45:21 +00:00
if (!$count_only && !empty($p['limit'])) {
2021-09-02 22:18:08 +00:00
$r .= $this->con->limit($p['limit']);
}
return $this->con->select($r);
}
2021-09-03 07:45:21 +00:00
public function addLog($group, $action, $logs)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
try {
2022-11-30 21:35:28 +00:00
$cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
$this->con->writeLock(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
2021-09-02 22:18:08 +00:00
2022-11-18 20:24:30 +00:00
$cur->activity_id = $this->getNextId();
$cur->activity_type = $this->ns;
$cur->blog_id = $this->blog;
$cur->activity_group = $this->con->escape((string) $group);
2021-09-02 22:18:08 +00:00
$cur->activity_action = $this->con->escape((string) $action);
2022-11-18 20:24:30 +00:00
$cur->activity_logs = self::encode($logs);
$cur->activity_dt = date('Y-m-d H:i:s');
2021-09-02 22:18:08 +00:00
$cur->insert();
$this->con->unlock();
2021-09-03 07:45:21 +00:00
} catch (Exception $e) {
2021-09-02 22:18:08 +00:00
$this->con->unlock();
2022-11-18 20:24:30 +00:00
dcCore::app()->error->add($e->getMessage());
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
// Test if email report is needed
2021-09-02 22:18:08 +00:00
$this->needReport();
}
private function parseLogs($rs)
{
2021-09-03 07:45:21 +00:00
if ($rs->isEmpty()) {
return '';
}
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
// @todo move this in function
2022-11-18 20:24:30 +00:00
include __DIR__ . '/lib.parselogs.config.php';
2021-09-02 22:18:08 +00:00
$from = time();
2022-11-18 20:24:30 +00:00
$to = 0;
$res = $blog = $group = '';
$tz = $this->_global ? 'UTC' : dcCore::app()->blog->settings->system->blog_timezone;
2021-09-02 22:18:08 +00:00
$dt = $this->settings[$this->_global]['dateformat'];
$dt = empty($dt) ? '%Y-%m-%d %H:%M:%S' : $dt;
$tpl = $this->settings[$this->_global]['mailformat'];
$tpl = $tpl == 'html' ? $format['html'] : $format['plain'];
$blog_open = $group_open = false;
2022-11-18 20:24:30 +00:00
while ($rs->fetch()) {
2021-09-03 07:45:21 +00:00
// blog
if ($rs->blog_id != $blog && $this->_global) {
2021-09-02 22:18:08 +00:00
if ($group_open) {
$res .= $tpl['group_close'];
$group_open = false;
}
if ($blog_open) {
$res .= $tpl['blog_close'];
}
2022-11-18 20:24:30 +00:00
$blog = $rs->blog_id;
2021-09-02 22:18:08 +00:00
$group = '';
2021-09-03 07:45:21 +00:00
$res .= str_replace(
2022-11-18 20:24:30 +00:00
['%TEXT%', '%URL%'],
[$rs->blog_name . ' (' . $rs->blog_id . ')', $rs->blog_url],
2021-09-03 07:45:21 +00:00
$tpl['blog_title']
) . $tpl['blog_open'];
2021-09-02 22:18:08 +00:00
$blog_open = true;
}
2021-09-03 07:45:21 +00:00
if (isset($this->groups[$rs->activity_group])) {
// Type
if ($rs->activity_group != $group) {
2021-09-02 22:18:08 +00:00
if ($group_open) {
$res .= $tpl['group_close'];
}
$group = $rs->activity_group;
2021-09-03 07:45:21 +00:00
$res .= str_replace(
'%TEXT%',
__($this->groups[$group]['title']),
$tpl['group_title']
) . $tpl['group_open'];
2021-09-02 22:18:08 +00:00
$group_open = true;
}
2021-09-03 07:45:21 +00:00
// Action
2021-09-02 22:18:08 +00:00
$time = strtotime($rs->activity_dt);
$data = self::decode($rs->activity_logs);
2021-09-03 07:45:21 +00:00
$res .= str_replace(
2022-11-18 20:24:30 +00:00
['%TIME%', '%TEXT%'],
2021-09-03 07:45:21 +00:00
[dt::str($dt, $time, $tz), vsprintf(__($this->groups[$group]['actions'][$rs->activity_action]['msg']), $data)],
$tpl['action']
);
2021-09-02 22:18:08 +00:00
# Period
2021-09-03 07:45:21 +00:00
if ($time < $from) {
$from = $time;
}
if ($time > $to) {
$to = $time;
}
2021-09-02 22:18:08 +00:00
}
}
if ($group_open) {
$res .= $tpl['group_close'];
}
if ($blog_open) {
$res .= $tpl['blog_close'];
}
if ($to == 0) {
2021-09-03 07:45:21 +00:00
$res .= str_replace('%TEXT%', __('An error occured when parsing report.'), $tpl['error']);
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
// Top of msg
if (empty($res)) {
return '';
}
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
$period = str_replace(
'%TEXT%',
__('Activity report'),
$tpl['period_title']
) . $tpl['period_open'];
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
$period .= str_replace(
'%TEXT%',
__("You received a message from your blog's activity report module."),
$tpl['info']
);
if (!$this->_global) {
2022-11-18 20:24:30 +00:00
$period .= str_replace('%TEXT%', $rs->blog_name, $tpl['info']);
$period .= str_replace('%TEXT%', $rs->blog_url, $tpl['info']);
2021-09-03 07:45:21 +00:00
}
$period .= str_replace(
'%TEXT%',
sprintf(__('Period from %s to %s'), dt::str($dt, $from, $tz), dt::str($dt, $to, $tz)),
2022-11-18 20:24:30 +00:00
$tpl['info']
);
2021-09-02 22:18:08 +00:00
$period .= $tpl['period_close'];
2021-09-03 07:45:21 +00:00
$res = str_replace(['%PERIOD%', '%TEXT%'], [$period, $res], $tpl['page']);
2021-09-02 22:18:08 +00:00
return $res;
}
private function obsoleteLogs()
{
2021-09-03 07:45:21 +00:00
// Get blogs and logs count
2021-09-02 22:18:08 +00:00
$rs = $this->con->select(
2022-11-18 20:24:30 +00:00
'SELECT blog_id ' .
2022-11-30 21:35:28 +00:00
'FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
2021-09-03 07:45:21 +00:00
"WHERE activity_type='" . $this->ns . "' " .
2021-09-02 22:18:08 +00:00
'GROUP BY blog_id '
);
2021-09-03 07:45:21 +00:00
if ($rs->isEmpty()) {
return null;
}
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
while ($rs->fetch()) {
2022-11-18 20:24:30 +00:00
$ts = time();
$obs_blog = dt::str('%Y-%m-%d %H:%M:%S', $ts - (int) $this->settings[0]['obsolete']);
$obs_global = dt::str('%Y-%m-%d %H:%M:%S', $ts - (int) $this->settings[1]['obsolete']);
2021-09-02 22:18:08 +00:00
$this->con->execute(
2022-11-30 21:35:28 +00:00
'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
2021-09-03 07:45:21 +00:00
"WHERE activity_type='" . $this->ns . "' " .
"AND (activity_dt < TIMESTAMP '" . $obs_blog . "' " .
"OR activity_dt < TIMESTAMP '" . $obs_global . "') " .
2022-11-18 20:24:30 +00:00
"AND blog_id = '" . $this->con->escape($rs->blog_id) . "' "
2021-09-02 22:18:08 +00:00
);
2021-09-03 07:45:21 +00:00
if ($this->con->changes()) {
try {
2022-11-30 21:35:28 +00:00
$cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
$this->con->writeLock(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
2021-09-02 22:18:08 +00:00
2022-11-18 20:24:30 +00:00
$cur->activity_id = $this->getNextId();
$cur->activity_type = $this->ns;
$cur->blog_id = $rs->blog_id;
$cur->activity_group = 'activityReport';
2021-09-02 22:18:08 +00:00
$cur->activity_action = 'message';
2022-11-18 20:24:30 +00:00
$cur->activity_logs = self::encode(__('Activity report deletes some old logs.'));
$cur->activity_dt = date('Y-m-d H:i:s');
2021-09-02 22:18:08 +00:00
$cur->insert();
$this->con->unlock();
2021-09-03 07:45:21 +00:00
} catch (Exception $e) {
2021-09-02 22:18:08 +00:00
$this->con->unlock();
2022-11-18 20:24:30 +00:00
dcCore::app()->error->add($e->getMessage());
2021-09-02 22:18:08 +00:00
}
}
}
}
private function cleanLogs()
{
$this->con->execute(
2022-11-30 21:35:28 +00:00
'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
2021-09-03 07:45:21 +00:00
"WHERE activity_type='" . $this->ns . "' " .
2022-11-18 20:24:30 +00:00
'AND activity_blog_status = 1 ' .
'AND activity_super_status = 1 '
2021-09-02 22:18:08 +00:00
);
}
public function deleteLogs()
{
2022-11-18 20:24:30 +00:00
if (!dcCore::app()->auth->isSuperAdmin()) {
2021-09-03 07:45:21 +00:00
return null;
}
2021-09-02 22:18:08 +00:00
return $this->con->execute(
2022-11-30 21:35:28 +00:00
'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
2021-09-03 07:45:21 +00:00
"WHERE activity_type='" . $this->ns . "' "
2021-09-02 22:18:08 +00:00
);
}
2021-09-03 07:45:21 +00:00
private function updateStatus($from_date_ts, $to_date_ts)
2021-09-02 22:18:08 +00:00
{
2022-11-30 21:35:28 +00:00
$r = 'UPDATE ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ';
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
if ($this->_global) {
2022-11-18 20:24:30 +00:00
$r .= 'SET activity_super_status = 1 WHERE blog_id IS NOT NULL ';
2021-09-03 07:45:21 +00:00
} else {
$r .= "SET activity_blog_status = 1 WHERE blog_id = '" . $this->blog . "' ";
2021-09-02 22:18:08 +00:00
}
2022-11-18 20:24:30 +00:00
$r .= "AND activity_type = '" . $this->ns . "' " .
"AND activity_dt >= TIMESTAMP '" . date('Y-m-d H:i:s', $from_date_ts) . "' " .
"AND activity_dt < TIMESTAMP '" . date('Y-m-d H:i:s', $to_date_ts) . "' ";
2021-09-02 22:18:08 +00:00
$this->con->execute($r);
}
public function getNextId()
{
return $this->con->select(
2022-11-30 21:35:28 +00:00
'SELECT MAX(activity_id) FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME
2021-09-02 22:18:08 +00:00
)->f(0) + 1;
}
# Lock a file to see if an update is ongoing
public function lockUpdate()
{
2021-09-03 07:45:21 +00:00
try {
2021-09-02 22:18:08 +00:00
# Need flock function
if (!function_exists('flock')) {
2022-11-18 20:24:30 +00:00
throw new Exception("Can't call php function named flock");
2021-09-02 22:18:08 +00:00
}
# Cache writable ?
if (!is_writable(DC_TPL_CACHE)) {
throw new Exception("Can't write in cache fodler");
}
# Set file path
2022-11-18 20:24:30 +00:00
$f_md5 = $this->_global ? md5(DC_MASTER_KEY) : md5($this->blog);
$cached_file = sprintf(
'%s/%s/%s/%s/%s.txt',
2021-09-02 22:18:08 +00:00
DC_TPL_CACHE,
2022-12-15 23:32:15 +00:00
initActivityReport::CACHE_DIR_NAME,
2021-09-03 07:45:21 +00:00
substr($f_md5, 0, 2),
substr($f_md5, 2, 2),
2021-09-02 22:18:08 +00:00
$f_md5
);
# Real path
2021-09-03 07:45:21 +00:00
$cached_file = path::real($cached_file, false);
// make dir
2021-09-02 22:18:08 +00:00
if (!is_dir(dirname($cached_file))) {
2022-11-18 20:24:30 +00:00
files::makeDir(dirname($cached_file), true);
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
//ake file
2021-09-02 22:18:08 +00:00
if (!file_exists($cached_file)) {
!$fp = @fopen($cached_file, 'w');
if ($fp === false) {
2022-11-18 20:24:30 +00:00
throw new Exception("Can't create file");
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
fwrite($fp, '1', strlen('1'));
2021-09-02 22:18:08 +00:00
fclose($fp);
}
2021-09-03 07:45:21 +00:00
// open file
2021-09-02 22:18:08 +00:00
if (!($fp = @fopen($cached_file, 'r+'))) {
2022-11-18 20:24:30 +00:00
throw new Exception("Can't open file");
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
// lock file
2022-11-27 14:35:03 +00:00
if (!flock($fp, LOCK_EX | LOCK_NB)) {
2022-11-27 21:19:52 +00:00
//throw new Exception("Can't lock file");
return false;
2021-09-02 22:18:08 +00:00
}
2021-09-03 07:45:21 +00:00
if ($this->_global) {
2021-09-02 22:18:08 +00:00
$this->lock_global = $fp;
2021-09-03 07:45:21 +00:00
} else {
2021-09-02 22:18:08 +00:00
$this->lock_blog = $fp;
}
2022-11-18 20:24:30 +00:00
2021-09-02 22:18:08 +00:00
return true;
2021-09-03 07:45:21 +00:00
} catch (Exception $e) {
// what ?
2021-09-02 22:18:08 +00:00
throw $e;
}
2022-11-18 20:24:30 +00:00
2021-09-02 22:18:08 +00:00
return false;
}
public function unlockUpdate()
{
2021-09-03 07:45:21 +00:00
if ($this->_global) {
2021-09-02 22:18:08 +00:00
@fclose($this->lock_global);
$this->lock_global = null;
2022-11-27 14:35:03 +00:00
} elseif ($this->lock_blog) {
2021-09-02 22:18:08 +00:00
@fclose($this->lock_blog);
$this->lock_blog = null;
}
}
public static function hasMailer()
{
return function_exists('mail') || function_exists('_mail');
}
2021-09-03 07:45:21 +00:00
public function needReport($force = false)
2021-09-02 22:18:08 +00:00
{
2021-09-03 07:45:21 +00:00
try {
// Check if server has mail function
if (!self::hasMailer()) {
2021-09-02 22:18:08 +00:00
throw new Exception('No mail fonction');
}
2021-09-03 07:45:21 +00:00
// Limit to one update at a time
2021-09-02 22:18:08 +00:00
$this->lockUpdate();
$send = false;
2022-11-18 20:24:30 +00:00
$now = time();
2021-09-02 22:18:08 +00:00
2022-11-18 20:24:30 +00:00
$active = (bool) $this->settings[$this->_global]['active'];
2021-09-02 22:18:08 +00:00
$mailinglist = $this->settings[$this->_global]['mailinglist'];
2022-11-18 20:24:30 +00:00
$mailformat = $this->settings[$this->_global]['mailformat'];
$requests = $this->settings[$this->_global]['requests'];
$lastreport = (int) $this->settings[$this->_global]['lastreport'];
$interval = (int) $this->settings[$this->_global]['interval'];
$blogs = $this->settings[$this->_global]['blogs'];
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
if ($force) {
$lastreport = 0;
}
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
// Check if report is needed
2022-11-18 20:24:30 +00:00
if ($active && !empty($mailinglist) && !empty($requests) && !empty($blogs)
&& ($lastreport + $interval) < $now
2021-09-03 07:45:21 +00:00
) {
// Get datas
$params = [
'from_date_ts' => $lastreport,
2022-11-18 20:24:30 +00:00
'to_date_ts' => $now,
'blog_id' => $blogs,
'sql' => self::requests2params($requests),
'order' => 'blog_id ASC, activity_group ASC, activity_action ASC, activity_dt ASC ',
2021-09-03 07:45:21 +00:00
];
2021-09-02 22:18:08 +00:00
$logs = $this->getLogs($params);
2021-09-03 07:45:21 +00:00
if (!$logs->isEmpty()) {
// Datas to readable text
2021-09-02 22:18:08 +00:00
$content = $this->parseLogs($logs);
2021-09-03 07:45:21 +00:00
if (!empty($content)) {
// Send mails
$send = $this->sendReport($mailinglist, $content, $mailformat);
2021-09-02 22:18:08 +00:00
}
}
2021-09-03 07:45:21 +00:00
// Update db
if ($send || $this->_global) { // if global : delete all blog logs even if not selected
$this->updateStatus($lastreport, $now);
2021-09-02 22:18:08 +00:00
$this->cleanLogs();
2021-09-03 07:45:21 +00:00
$this->setSetting('lastreport', $now);
2021-09-02 22:18:08 +00:00
}
}
2021-09-03 07:45:21 +00:00
// If this is on a blog, we need to test superAdmin report
if (!$this->_global) {
2021-09-02 22:18:08 +00:00
$this->_global = true;
$this->needReport();
$this->_global = false;
2021-09-03 07:45:21 +00:00
if ($send) {
2022-11-18 20:24:30 +00:00
dcCore::app()->callBehavior('messageActivityReport', 'Activity report has been successfully send by mail.');
2021-09-02 22:18:08 +00:00
}
}
$this->unlockUpdate();
2021-09-03 07:45:21 +00:00
} catch (Exception $e) {
2021-09-02 22:18:08 +00:00
$this->unlockUpdate();
}
2022-11-18 20:24:30 +00:00
2021-09-02 22:18:08 +00:00
return true;
}
2022-11-18 20:24:30 +00:00
private function sendReport($recipients, $message, $mailformat = ' ')
2021-09-02 22:18:08 +00:00
{
2021-09-04 13:23:35 +00:00
if (!is_array($recipients) || empty($message)) {
2021-09-03 07:45:21 +00:00
return false;
}
2022-11-18 20:24:30 +00:00
$mailformat = $mailformat == 'html' ? 'html' : 'plain';
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
// Checks recipients addresses
$rc2 = [];
foreach ($recipients as $v) {
2021-09-02 22:18:08 +00:00
$v = trim($v);
2021-09-03 07:45:21 +00:00
if (!empty($v) && text::isEmail($v)) {
2021-09-02 22:18:08 +00:00
$rc2[] = $v;
}
}
$recipients = $rc2;
unset($rc2);
2021-09-03 07:45:21 +00:00
if (empty($recipients)) {
return false;
}
2021-09-02 22:18:08 +00:00
# Sending mails
2021-09-03 07:45:21 +00:00
try {
2021-09-04 13:23:35 +00:00
$subject = mb_encode_mimeheader(
2022-11-18 20:24:30 +00:00
($this->_global ? '[' . dcCore::app()->blog->name . '] ' : '') . __('Blog activity report'),
'UTF-8',
'B'
2021-09-04 13:23:35 +00:00
);
2022-11-18 20:24:30 +00:00
$headers = [];
2021-09-04 13:23:35 +00:00
$headers[] = 'From: ' . (defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
2022-11-18 20:24:30 +00:00
$headers[] = 'Content-Type: text/' . $mailformat . '; charset=UTF-8;';
2021-09-04 13:23:35 +00:00
//$headers[] = 'MIME-Version: 1.0';
//$headers[] = 'X-Originating-IP: ' . mb_encode_mimeheader(http::realIP(), 'UTF-8', 'B');
//$headers[] = 'X-Mailer: Dotclear';
2022-11-18 20:24:30 +00:00
//$headers[] = 'X-Blog-Id: ' . mb_encode_mimeheader(dcCore::app()->blog->id), 'UTF-8', 'B');
//$headers[] = 'X-Blog-Name: ' . mb_encode_mimeheader(dcCore::app()->blog->name), 'UTF-8', 'B');
//$headers[] = 'X-Blog-Url: ' . mb_encode_mimeheader(dcCore::app()->blog->url), 'UTF-8', 'B');
2021-09-02 22:18:08 +00:00
$done = true;
2021-09-03 07:45:21 +00:00
foreach ($recipients as $email) {
2021-09-04 13:23:35 +00:00
if (true !== mail::sendMail($email, $subject, $message, $headers)) {
2021-09-02 22:18:08 +00:00
$done = false;
}
}
2022-11-18 20:24:30 +00:00
} catch (Exception $e) {
2021-09-02 22:18:08 +00:00
$done = false;
}
2022-11-18 20:24:30 +00:00
2021-09-02 22:18:08 +00:00
return $done;
}
public function getUserCode()
{
2022-11-18 20:24:30 +00:00
$code = pack('a32', dcCore::app()->auth->userID()) .
pack('H*', crypt::hmac(DC_MASTER_KEY, dcCore::app()->auth->getInfo('user_pwd')));
2021-09-02 22:18:08 +00:00
return bin2hex($code);
}
public function checkUserCode($code)
{
2021-09-03 07:45:21 +00:00
$code = pack('H*', $code);
2021-09-02 22:18:08 +00:00
2021-09-03 07:45:21 +00:00
$user_id = trim(@pack('a32', substr($code, 0, 32)));
2022-11-18 20:24:30 +00:00
$pwd = @unpack('H40hex', substr($code, 32, 40));
2021-09-02 22:18:08 +00:00
if ($user_id === false || $pwd === false) {
return false;
}
$pwd = $pwd['hex'];
2021-09-03 07:45:21 +00:00
$strReq = 'SELECT user_id, user_pwd ' .
2022-11-30 21:35:28 +00:00
'FROM ' . dcCore::app()->prefix . dcAuth::USER_TABLE_NAME . ' ' .
2022-11-18 20:24:30 +00:00
"WHERE user_id = '" . dcCore::app()->con->escape($user_id) . "' ";
2021-09-02 22:18:08 +00:00
2022-11-18 20:24:30 +00:00
$rs = dcCore::app()->con->select($strReq);
2021-09-02 22:18:08 +00:00
if ($rs->isEmpty()) {
return false;
}
2022-11-18 20:24:30 +00:00
if (crypt::hmac(DC_MASTER_KEY, $rs->user_pwd) != $pwd) {
2021-09-02 22:18:08 +00:00
return false;
}
return $rs->user_id;
}
public static function encode($a)
{
return @base64_encode(@serialize($a));
}
public static function decode($a)
{
return @unserialize(@base64_decode($a));
}
2022-11-18 20:24:30 +00:00
}