2021-08-23 11:24:19 +00:00
|
|
|
<?php
|
2021-09-02 12:56:02 +00:00
|
|
|
/**
|
|
|
|
* @brief periodical, a plugin for Dotclear 2
|
|
|
|
*
|
|
|
|
* @package Dotclear
|
|
|
|
* @subpackage Plugin
|
|
|
|
*
|
|
|
|
* @author Jean-Christian Denis and contributors
|
|
|
|
*
|
|
|
|
* @copyright Jean-Christian Denis
|
|
|
|
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
|
|
|
*/
|
2021-08-23 11:24:19 +00:00
|
|
|
|
2021-08-23 22:52:29 +00:00
|
|
|
if (!defined('DC_RC_PATH')){
|
|
|
|
return;
|
|
|
|
}
|
2021-08-23 11:24:19 +00:00
|
|
|
|
|
|
|
class periodical
|
|
|
|
{
|
2021-08-23 22:52:29 +00:00
|
|
|
public $core;
|
|
|
|
public $con;
|
|
|
|
|
|
|
|
protected $table;
|
|
|
|
protected $blog;
|
|
|
|
private $lock = null;
|
|
|
|
|
|
|
|
public function __construct($core)
|
|
|
|
{
|
|
|
|
$this->core = $core;
|
|
|
|
$this->con = $core->con;
|
|
|
|
|
|
|
|
$this->table = $core->con->escape($core->prefix . 'periodical');
|
|
|
|
$this->blog = $core->con->escape($core->blog->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function openCursor()
|
|
|
|
{
|
|
|
|
return $this->con->openCursor($this->table);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get periods
|
|
|
|
public function getPeriods($params = [], $count_only = false)
|
|
|
|
{
|
|
|
|
if ($count_only) {
|
|
|
|
$q = 'SELECT count(T.periodical_id) ';
|
|
|
|
} else {
|
|
|
|
$q = 'SELECT T.periodical_id, T.periodical_type, ';
|
|
|
|
|
|
|
|
if (!empty($params['columns']) && is_array($params['columns'])) {
|
|
|
|
$q .= implode(', ', $params['columns']) . ', ';
|
|
|
|
}
|
|
|
|
$q .=
|
|
|
|
'T.periodical_title, T.periodical_tz, ' .
|
|
|
|
'T.periodical_curdt, T.periodical_enddt, ' .
|
|
|
|
'T.periodical_pub_int, T.periodical_pub_nb ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$q .= 'FROM ' . $this->table . ' T ';
|
|
|
|
|
|
|
|
if (!empty($params['from'])) {
|
|
|
|
$q .= $params['from'] . ' ';
|
|
|
|
}
|
|
|
|
$q .= "WHERE T.blog_id = '" . $this->blog . "' ";
|
|
|
|
|
|
|
|
if (isset($params['periodical_type'])) {
|
|
|
|
if (is_array($params['periodical_type']) && !empty($params['periodical_type'])) {
|
|
|
|
$q .= 'AND T.periodical_type ' . $this->con->in($params['periodical_type']);
|
|
|
|
} elseif ($params['periodical_type'] != '') {
|
|
|
|
$q .= "AND T.periodical_type = '" . $this->con->escape($params['periodical_type']) . "' ";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$q .= "AND T.periodical_type = 'post' ";
|
|
|
|
}
|
|
|
|
if (!empty($params['periodical_id'])) {
|
|
|
|
if (is_array($params['periodical_id'])) {
|
|
|
|
array_walk($params['periodical_id'], create_function('&$v,$k', 'if($v!==null){$v=(integer)$v;}'));
|
|
|
|
} else {
|
|
|
|
$params['periodical_id'] = [(integer) $params['periodical_id']];
|
|
|
|
}
|
|
|
|
$q .= 'AND T.periodical_id ' . $this->con->in($params['periodical_id']);
|
|
|
|
}
|
|
|
|
if (!empty($params['periodical_title'])) {
|
|
|
|
$q .= "AND T.periodical_title = '" . $this->con->escape($params['periodical_title']) . "' ";
|
|
|
|
}
|
|
|
|
if (!empty($params['sql'])) {
|
|
|
|
$q .= $params['sql'].' ';
|
|
|
|
}
|
|
|
|
if (!$count_only) {
|
|
|
|
if (!empty($params['order'])) {
|
|
|
|
$q .= 'ORDER BY ' . $this->con->escape($params['order']).' ';
|
|
|
|
} else {
|
|
|
|
$q .= 'ORDER BY T.periodical_id ASC ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$count_only && !empty($params['limit'])) {
|
|
|
|
$q .= $this->con->limit($params['limit']);
|
|
|
|
}
|
|
|
|
$rs = $this->con->select($q);
|
|
|
|
$rs->core = $this->core;
|
|
|
|
$rs->periodical = $this;
|
|
|
|
|
|
|
|
return $rs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addPeriod($cur)
|
|
|
|
{
|
|
|
|
$this->con->writeLock($this->table);
|
|
|
|
|
|
|
|
try {
|
|
|
|
$id = $this->con->select(
|
|
|
|
'SELECT MAX(periodical_id) FROM ' . $this->table
|
|
|
|
)->f(0) + 1;
|
|
|
|
|
|
|
|
$cur->periodical_id = $id;
|
|
|
|
$cur->blog_id = $this->blog;
|
|
|
|
$cur->periodical_type = 'post';
|
|
|
|
$cur->periodical_tz = $this->core->auth->getInfo('user_tz');
|
|
|
|
$cur->insert();
|
|
|
|
$this->con->unlock();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$this->con->unlock();
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
return $cur->periodical_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function updPeriod($period_id,$cur)
|
|
|
|
{
|
|
|
|
$period_id = (integer) $period_id;
|
|
|
|
|
|
|
|
if ($cur->periodical_tz == ''
|
|
|
|
&& ($cur->periodical_curdt != '' || $cur->periodical_enddt != '')) {
|
|
|
|
$cur->periodical_tz = $this->core->auth->getInfo('user_tz');
|
|
|
|
}
|
|
|
|
$cur->update(
|
|
|
|
"WHERE blog_id = '" . $this->blog . "' " .
|
|
|
|
"AND periodical_id = " . $period_id . " "
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Delete a period
|
|
|
|
public function delPeriod($period_id)
|
|
|
|
{
|
|
|
|
$period_id = (integer) $period_id;
|
|
|
|
|
|
|
|
$params = [];
|
|
|
|
$params['periodical_id'] = $period_id;
|
|
|
|
$params['post_status'] = '';
|
|
|
|
$rs = $this->getPosts($params);
|
|
|
|
|
|
|
|
if (!$rs->isEmpty()) {
|
|
|
|
throw new Exception('Periodical is not empty');
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->con->execute(
|
|
|
|
'DELETE FROM ' . $this->table . ' ' .
|
|
|
|
"WHERE blog_id = '" . $this->blog . "' " .
|
|
|
|
"AND periodical_id = " . $period_id . " "
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Remove all posts related to a period
|
|
|
|
public function delPeriodPosts($period_id)
|
|
|
|
{
|
|
|
|
$params = [];
|
|
|
|
$params['post_status'] = '';
|
|
|
|
$params['periodical_id'] = (integer) $period_id;
|
|
|
|
|
|
|
|
$rs = $this->getPosts($params);
|
|
|
|
|
|
|
|
if ($rs->isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$ids = array();
|
|
|
|
while($rs->fetch())
|
|
|
|
{
|
|
|
|
$ids[] = $rs->post_id;
|
|
|
|
}
|
|
|
|
|
2021-08-23 23:32:27 +00:00
|
|
|
if (empty($ids)) {
|
2021-08-23 22:52:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->con->execute(
|
|
|
|
'DELETE FROM ' . $this->core->prefix . 'meta ' .
|
|
|
|
"WHERE meta_type = 'periodical' " .
|
|
|
|
"AND post_id " . $this->con->in($ids)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get posts related to periods
|
|
|
|
public function getPosts($params = [], $count_only = false)
|
|
|
|
{
|
|
|
|
if (!isset($params['columns'])) {
|
|
|
|
$params['columns'] = [];
|
|
|
|
}
|
|
|
|
if (!isset($params['from'])) {
|
|
|
|
$params['from'] = '';
|
|
|
|
}
|
|
|
|
if (!isset($params['sql'])) {
|
|
|
|
$params['sql'] = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
$params['columns'][] = 'T.periodical_id';
|
|
|
|
$params['columns'][] = 'T.periodical_title';
|
|
|
|
$params['columns'][] = 'T.periodical_type';
|
|
|
|
$params['columns'][] = 'T.periodical_tz';
|
|
|
|
$params['columns'][] = 'T.periodical_curdt';
|
|
|
|
$params['columns'][] = 'T.periodical_enddt';
|
|
|
|
$params['columns'][] = 'T.periodical_pub_int';
|
|
|
|
$params['columns'][] = 'T.periodical_pub_nb';
|
|
|
|
|
|
|
|
$params['from'] .= 'LEFT JOIN ' . $this->core->prefix . 'meta R ON P.post_id = R.post_id ';
|
|
|
|
$params['from'] .= 'LEFT JOIN ' . $this->table . ' T ON CAST(T.periodical_id as char)=R.meta_id ';
|
|
|
|
|
|
|
|
$params['sql'] .= "AND R.meta_type = 'periodical' ";
|
|
|
|
$params['sql'] .= "AND T.periodical_type = 'post' ";
|
|
|
|
|
|
|
|
if (!empty($params['periodical_id'])) {
|
|
|
|
if (is_array($params['periodical_id'])) {
|
2021-10-23 21:36:35 +00:00
|
|
|
array_walk($params['periodical_id'], function ($v) { if ($v !== null) { $v = (integer) $v; } });
|
2021-08-23 22:52:29 +00:00
|
|
|
} else {
|
|
|
|
$params['periodical_id'] = [(integer) $params['periodical_id']];
|
|
|
|
}
|
|
|
|
$params['sql'] .= 'AND T.periodical_id ' . $this->con->in($params['periodical_id']);
|
|
|
|
unset($params['periodical_id']);
|
|
|
|
}
|
|
|
|
if ($this->core->auth->check('admin', $this->core->blog->id)) {
|
|
|
|
if (isset($params['post_status'])) {
|
|
|
|
if ($params['post_status'] != '') {
|
|
|
|
$params['sql'] .= 'AND P.post_status = ' . (integer) $params['post_status'] . ' ';
|
|
|
|
}
|
|
|
|
unset($params['post_status']);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$params['sql'] .= 'AND P.post_status = -2 ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$rs = $this->core->blog->getPosts($params, $count_only);
|
|
|
|
$rs->periodical = $this;
|
|
|
|
|
|
|
|
return $rs;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Add post to periodical
|
|
|
|
public function addPost($period_id, $post_id)
|
|
|
|
{
|
|
|
|
$period_id = (integer) $period_id;
|
|
|
|
$post_id = (integer) $post_id;
|
|
|
|
|
|
|
|
# Check if exists
|
|
|
|
$rs = $this->getPosts(array('post_id' => $post_id, 'periodical_id' => $period_id));
|
|
|
|
if (!$rs->isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$cur = $this->con->openCursor($this->core->prefix .'meta');
|
|
|
|
$this->con->writeLock($this->core->prefix . 'meta');
|
2021-09-02 12:56:02 +00:00
|
|
|
|
2021-08-23 22:52:29 +00:00
|
|
|
try {
|
|
|
|
$cur->post_id = $post_id;
|
|
|
|
$cur->meta_id = $period_id;
|
|
|
|
$cur->meta_type = 'periodical';
|
|
|
|
$cur->insert();
|
|
|
|
$this->con->unlock();
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$this->con->unlock();
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Delete post from periodical
|
|
|
|
public function delPost($post_id)
|
|
|
|
{
|
|
|
|
$post_id = (integer) $post_id;
|
|
|
|
|
|
|
|
$this->con->execute(
|
|
|
|
'DELETE FROM ' . $this->core->prefix . 'meta ' .
|
|
|
|
"WHERE meta_type = 'periodical' " .
|
|
|
|
"AND post_id = '" . $post_id . "' "
|
|
|
|
);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Remove all posts without pending status from periodical
|
|
|
|
public function cleanPosts($period_id = null)
|
|
|
|
{
|
|
|
|
$params = [];
|
|
|
|
$params['post_status'] = '';
|
|
|
|
$params['sql'] = 'AND post_status != -2 ';
|
|
|
|
if ($period_id !== null) {
|
|
|
|
$params['periodical_id'] = (integer) $period_id;
|
|
|
|
}
|
|
|
|
$rs = $this->getPosts($params);
|
|
|
|
|
|
|
|
if ($rs->isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$ids = array();
|
|
|
|
while($rs->fetch()) {
|
|
|
|
$ids[] = $rs->post_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($ids)) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-02 12:56:02 +00:00
|
|
|
|
2021-08-23 22:52:29 +00:00
|
|
|
$this->con->execute(
|
|
|
|
'DELETE FROM ' . $this->core->prefix . 'meta ' .
|
|
|
|
"WHERE meta_type = 'periodical' " .
|
|
|
|
"AND post_id " . $this->con->in($ids)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getTimesCombo()
|
|
|
|
{
|
2021-08-23 23:32:27 +00:00
|
|
|
return [
|
2021-10-23 21:36:35 +00:00
|
|
|
__('Hourly') => 'hour',
|
2021-08-23 22:52:29 +00:00
|
|
|
__('twice a day') => 'halfday',
|
2021-10-23 21:36:35 +00:00
|
|
|
__('Daily') => 'day',
|
|
|
|
__('Weekly') => 'week',
|
|
|
|
__('Monthly') => 'month'
|
2021-08-23 22:52:29 +00:00
|
|
|
];
|
|
|
|
}
|
2021-09-02 12:56:02 +00:00
|
|
|
|
2021-08-23 22:52:29 +00:00
|
|
|
public static function getNextTime($ts, $period)
|
|
|
|
{
|
|
|
|
$ts = (integer) $ts;
|
|
|
|
$e = explode(',', date('H,i,s,n,j,Y', $ts));
|
|
|
|
switch($period)
|
|
|
|
{
|
|
|
|
case 'hour':
|
2021-10-23 21:36:35 +00:00
|
|
|
$new_ts = mktime($e[0] + 1, $e[1], $e[2], $e[3], $e[4], $e[5]);
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'halfday':
|
2021-10-23 21:36:35 +00:00
|
|
|
$new_ts = mktime($e[0] + 12, $e[1], $e[2], $e[3], $e[4], $e[5]);
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'day':
|
2021-10-23 21:36:35 +00:00
|
|
|
$new_ts = mktime($e[0], $e[1] ,$e[2], $e[3], $e[4] + 1, $e[5]);
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'week':
|
2021-10-23 21:36:35 +00:00
|
|
|
$new_ts = mktime($e[0], $e[1], $e[2], $e[3], $e[4] + 7, $e[5]);
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'month':
|
2021-10-23 21:36:35 +00:00
|
|
|
$new_ts = mktime($e[0], $e[1], $e[2], $e[3] + 1, $e[4], $e[5]);
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
$new_ts = 0;
|
2021-10-23 21:36:35 +00:00
|
|
|
throw new Exception(__('Unknow frequence'));
|
2021-08-23 22:52:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return $new_ts;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Lock a file to see if an update is ongoing
|
|
|
|
public function lockUpdate()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
# Need flock function
|
|
|
|
if (!function_exists('flock')) {
|
|
|
|
throw New Exception("Can't call php function named flock");
|
|
|
|
}
|
|
|
|
# Cache writable ?
|
|
|
|
if (!is_writable(DC_TPL_CACHE)) {
|
|
|
|
throw new Exception("Can't write in cache fodler");
|
|
|
|
}
|
|
|
|
# Set file path
|
|
|
|
$f_md5 = md5($this->blog);
|
|
|
|
$cached_file = sprintf(
|
|
|
|
'%s/%s/%s/%s/%s.txt',
|
|
|
|
DC_TPL_CACHE,
|
|
|
|
'periodical',
|
|
|
|
substr($f_md5, 0, 2),
|
|
|
|
substr($f_md5, 2, 2),
|
|
|
|
$f_md5
|
|
|
|
);
|
|
|
|
# Real path
|
|
|
|
$cached_file = path::real($cached_file, false);
|
|
|
|
# Make dir
|
|
|
|
if (!is_dir(dirname($cached_file))) {
|
|
|
|
files::makeDir(dirname($cached_file), true);
|
|
|
|
}
|
|
|
|
# Make file
|
|
|
|
if (!file_exists($cached_file)) {
|
|
|
|
!$fp = @fopen($cached_file, 'w');
|
|
|
|
if ($fp === false) {
|
|
|
|
throw New Exception("Can't create file");
|
|
|
|
}
|
|
|
|
fwrite($fp, '1', strlen('1'));
|
|
|
|
fclose($fp);
|
|
|
|
}
|
|
|
|
# Open file
|
|
|
|
if (!($fp = @fopen($cached_file, 'r+'))) {
|
|
|
|
throw New Exception("Can't open file");
|
|
|
|
}
|
|
|
|
# Lock file
|
|
|
|
if (!flock($fp, LOCK_EX)) {
|
|
|
|
throw New Exception("Can't lock file");
|
|
|
|
}
|
|
|
|
$this->lock = $fp;
|
|
|
|
return true;
|
|
|
|
} catch (Exception $e) {
|
|
|
|
throw $e;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function unlockUpdate()
|
|
|
|
{
|
|
|
|
@fclose($this->lock);
|
|
|
|
$this->lock = null;
|
|
|
|
}
|
|
|
|
}
|