Compare commits
10 Commits
8bcb572e28
...
90596323e1
Author | SHA1 | Date |
---|---|---|
Jean-Christian Paul Denis | 90596323e1 | |
Jean-Christian Paul Denis | ff58c0ba47 | |
Jean-Christian Paul Denis | 9f3108761c | |
Jean-Christian Paul Denis | 2a3a037e38 | |
Jean-Christian Paul Denis | 56552d12d3 | |
“philippe | 954f9ffb7f | |
“philippe | 2df4a4005e | |
“philippe | 90331d5159 | |
Jean-Christian Paul Denis | b1e0ecbc7f | |
Jean-Christian Paul Denis | da756d7625 |
|
@ -14,7 +14,7 @@ $this->registerModule(
|
|||
'Dotclear Watch',
|
||||
'Send report about your Dotclear',
|
||||
'Jean-Christian Denis and contributors',
|
||||
'0.3',
|
||||
'0.5',
|
||||
[
|
||||
'requires' => [
|
||||
['php', '7.4'],
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<modules xmlns:da="http://dotaddict.org/da/">
|
||||
<module id="DotclearWatch">
|
||||
<name>Dotclear Watch</name>
|
||||
<version>0.3</version>
|
||||
<version>0.5</version>
|
||||
<author>Jean-Christian Denis and contributors</author>
|
||||
<desc>Send report about your Dotclear</desc>
|
||||
<file>https://github.com/JcDenis/DotclearWatch/releases/download/v0.3/plugin-DotclearWatch.zip</file>
|
||||
<file>https://github.com/JcDenis/DotclearWatch/releases/download/v0.5/plugin-DotclearWatch.zip</file>
|
||||
<da:dcmin>2.27</da:dcmin>
|
||||
<da:details>http://plugins.dotaddict.org/dc2/details/DotclearWatch</da:details>
|
||||
<da:support>https://github.com/JcDenis/DotclearWatch/issues</da:support>
|
||||
|
|
|
@ -18,9 +18,9 @@ L10n::$locales['Settings are globals. Reports are by blog.']
|
|||
L10n::$locales['Hidden modules:'] = 'Modules cachés :';
|
||||
L10n::$locales['This is the comma separated list of plugins IDs and themes IDs to ignore in report.'] = 'C\'est la liste des modules cachés séparés par une virgule.';
|
||||
L10n::$locales['Distant API URL:'] = 'URL de l\'API distante :';
|
||||
L10n::$locales['This is the URL of the API to send report. Leave empty to reset value.'] = 'C\'est L\'URL de l\'API où sera envoyer le rapport. Laisser vide pour remettre par défaut.';
|
||||
L10n::$locales['This is the URL of the API to send report. Leave empty to reset value.'] = 'C\'est L\'URL de l\'API où sera envoyé le rapport. Laisser vide pour remettre par défaut.';
|
||||
L10n::$locales['Clear reports cache directory'] = 'Nettoyer le répertoire de cache des rapports.';
|
||||
L10n::$locales['This deletes all blogs reports in cache.'] = 'Ceci efface tous les rapports des blogs en cache.';
|
||||
L10n::$locales['Send report now'] = 'Envoyer le rapport maintenant';
|
||||
L10n::$locales['This sent report for current blog even if report exists in cache.'] = 'Ceci envoie le rapport pou r le blog courant même si un rapport existe en cache.';
|
||||
L10n::$locales['This sent report for current blog even if report exists in cache.'] = 'Ceci envoie le rapport pour le blog courant même si un rapport existe en cache.';
|
||||
L10n::$locales['Report that will be sent for this blog:'] = 'Rapport qui sera envoyé pour ce blog :';
|
||||
|
|
|
@ -32,7 +32,7 @@ msgid "Distant API URL:"
|
|||
msgstr "URL de l'API distante :"
|
||||
|
||||
msgid "This is the URL of the API to send report. Leave empty to reset value."
|
||||
msgstr "C'est L'URL de l'API où sera envoyer le rapport. Laisser vide pour remettre par défaut."
|
||||
msgstr "C'est L'URL de l'API où sera envoyé le rapport. Laisser vide pour remettre par défaut."
|
||||
|
||||
msgid "Clear reports cache directory"
|
||||
msgstr "Nettoyer le répertoire de cache des rapports."
|
||||
|
@ -44,7 +44,7 @@ msgid "Send report now"
|
|||
msgstr "Envoyer le rapport maintenant"
|
||||
|
||||
msgid "This sent report for current blog even if report exists in cache."
|
||||
msgstr "Ceci envoie le rapport pou r le blog courant même si un rapport existe en cache."
|
||||
msgstr "Ceci envoie le rapport pour le blog courant même si un rapport existe en cache."
|
||||
|
||||
msgid "Report that will be sent for this blog:"
|
||||
msgstr "Rapport qui sera envoyé pour ce blog :"
|
||||
|
|
|
@ -78,7 +78,12 @@ class Config extends Process
|
|||
|
||||
if (!empty($_POST['send_report'])) {
|
||||
Utils::sendReport(true);
|
||||
Notices::AddSuccessNotice(__('Report sent.'));
|
||||
$error = Utils::getError();
|
||||
if (!empty($error)) {
|
||||
Notices::AddWarningNotice($error);
|
||||
} else {
|
||||
Notices::AddSuccessNotice(__('Report sent.'));
|
||||
}
|
||||
}
|
||||
|
||||
dcCore::app()->admin->url->redirect('admin.plugins', ['module' => My::id(), 'conf' => '1']);
|
||||
|
|
182
src/Utils.php
182
src/Utils.php
|
@ -15,11 +15,11 @@ declare(strict_types=1);
|
|||
namespace Dotclear\Plugin\DotclearWatch;
|
||||
|
||||
use dcCore;
|
||||
use dcLog;
|
||||
use dcModuleDefine;
|
||||
use dcThemes;
|
||||
use Dotclear\Helper\Crypt;
|
||||
use Dotclear\Helper\File\Files;
|
||||
use Dotclear\Helper\File\Path;
|
||||
use Dotclear\Helper\Date;
|
||||
use Dotclear\Helper\Network\HttpClient;
|
||||
use Exception;
|
||||
|
||||
|
@ -32,7 +32,7 @@ class Utils
|
|||
public const DISTANT_API_URL = 'https://dotclear.watch/api';
|
||||
|
||||
/** @var string The distant API version */
|
||||
public const DISTANT_API_VERSION = '1.0';
|
||||
public const DISTANT_API_VERSION = '1.1';
|
||||
|
||||
/** @var array<int,string> The hiddens modules IDs */
|
||||
private static array $hiddens = [];
|
||||
|
@ -45,8 +45,14 @@ class Utils
|
|||
*/
|
||||
public static function addMark(): void
|
||||
{
|
||||
if (My::settings()->get('distant_api_url')) {
|
||||
echo '<p>' . __('/!\ Tracked by dotclear.watch') . '</p>';
|
||||
if (My::settings()->getGlobal('distant_api_url')) {
|
||||
echo sprintf(
|
||||
'<ul><li><a href="%s" title="%s" class="outgoing">%s<img src="%s" /></a></ul></li>',
|
||||
'https://dotclear.watch/statistics',
|
||||
__('DotclearWatch plugin statistics'),
|
||||
__('Tracked by dotclear.watch'),
|
||||
My::fileURL('icon.svg')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +144,18 @@ class Utils
|
|||
return self::check() ? self::uid() : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request error.
|
||||
*/
|
||||
public static function getError(): string
|
||||
{
|
||||
$rs = dcCore::app()->log->getLogs([
|
||||
'log_table' => My::id() . '_error',
|
||||
]);
|
||||
|
||||
return $rs->isEmpty() || !is_string($rs->f('log_msg')) ? '' : $rs->f('log_msg');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache directory.
|
||||
*/
|
||||
|
@ -162,31 +180,46 @@ class Utils
|
|||
return;
|
||||
}
|
||||
|
||||
$file = self::file();
|
||||
|
||||
if (!$force && !self::expired($file)) {
|
||||
if (!$force && !self::expired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$contents = self::contents();
|
||||
|
||||
self::write($file, $contents);
|
||||
self::write($contents);
|
||||
|
||||
try {
|
||||
$rsp = HttpClient::quickPost(sprintf(self::url(), 'report'), ['key' => self::key(), 'report' => $contents]);
|
||||
if ($rsp !== 'ok') {
|
||||
throw new Exception('bad API response');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
if ($force) {
|
||||
dcCore::app()->error->add(__('Dotclear.watch report failed'));
|
||||
$status = 500;
|
||||
$response = '';
|
||||
$url = sprintf(self::url(), 'report');
|
||||
$path = '';
|
||||
if ($client = HttpClient::initClient($url, $path)) {
|
||||
try {
|
||||
$client->setUserAgent('Dotclear.watch ' . My::id() . '/' . self::DISTANT_API_VERSION);
|
||||
$client->useGzip(false);
|
||||
$client->setPersistReferers(false);
|
||||
$client->post($path, ['key' => self::key(), 'report' => $contents]);
|
||||
|
||||
$status = $client->getStatus();
|
||||
$response = $client->getContent();
|
||||
unset($client);
|
||||
if ($status != 202) {
|
||||
self::error((string) '(' . $status . ') ' . $response);
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (Exception $e) {
|
||||
unset($client);
|
||||
}
|
||||
}
|
||||
|
||||
if ($force) {
|
||||
self::error('Dotclear.watch report failed');
|
||||
}
|
||||
}
|
||||
|
||||
private static function check(): bool
|
||||
{
|
||||
return defined('DC_CRYPT_ALGO') && defined('DC_TPL_CACHE') && is_dir(DC_TPL_CACHE) && is_writable(DC_TPL_CACHE);
|
||||
return defined('DC_CRYPT_ALGO');
|
||||
}
|
||||
|
||||
private static function key(): string
|
||||
|
@ -212,79 +245,102 @@ class Utils
|
|||
return md5(self::uid() . dcCore::app()->blog->uid);
|
||||
}
|
||||
|
||||
private static function url()
|
||||
private static function url(): string
|
||||
{
|
||||
$api_url = My::settings()->getGlobal('distant_api_url');
|
||||
|
||||
return (is_string($api_url) ? $api_url : self::DISTANT_API_URL) . '/' . self::DISTANT_API_VERSION . '/%s/' . self::uid();
|
||||
}
|
||||
|
||||
private static function file(): string
|
||||
{
|
||||
$file = self::buid();
|
||||
|
||||
return sprintf(
|
||||
'%s/%s/%s/%s/%s.json',
|
||||
(string) Path::real(DC_TPL_CACHE),
|
||||
My::id(),
|
||||
substr($file, 0, 2),
|
||||
substr($file, 2, 2),
|
||||
$file
|
||||
);
|
||||
}
|
||||
|
||||
private static function clear(): void
|
||||
{
|
||||
$path = (string) Path::real(DC_TPL_CACHE) . DIRECTORY_SEPARATOR . My::id();
|
||||
if (is_dir($path)) {
|
||||
Files::delTree($path);
|
||||
$rs = dcCore::app()->log->getLogs([
|
||||
'log_table' => [
|
||||
My::id() . '_report',
|
||||
My::id() . '_error',
|
||||
],
|
||||
]);
|
||||
|
||||
if ($rs->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$logs = [];
|
||||
while ($rs->fetch()) {
|
||||
$logs[] = (int) $rs->f('log_id');
|
||||
}
|
||||
dcCore::app()->log->delLogs($logs);
|
||||
}
|
||||
|
||||
private static function write(string $file, string $contents): void
|
||||
private static function error(string $message): void
|
||||
{
|
||||
$dir = dirname($file);
|
||||
if (!is_dir($dir)) {
|
||||
Files::makeDir($dir, true);
|
||||
}
|
||||
file_put_contents($file, $contents);
|
||||
self::clear();
|
||||
|
||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcLog::LOG_TABLE_NAME);
|
||||
$cur->setField('log_table', My::id() . '_error');
|
||||
$cur->setField('log_msg', $message);
|
||||
|
||||
dcCore::app()->log->addLog($cur);
|
||||
}
|
||||
|
||||
private static function read(string $file): string
|
||||
private static function write(string $contents): void
|
||||
{
|
||||
return is_file($file) && is_readable($file) ? (string) file_get_contents($file) : '';
|
||||
self::clear();
|
||||
|
||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcLog::LOG_TABLE_NAME);
|
||||
$cur->setField('log_table', My::id() . '_report');
|
||||
$cur->setField('log_msg', $contents);
|
||||
|
||||
dcCore::app()->log->addLog($cur);
|
||||
}
|
||||
|
||||
private static function expired(string $file): bool
|
||||
private static function read(): string
|
||||
{
|
||||
if (!is_file($file) || !is_readable($file) || ($time = filemtime($file)) === false) {
|
||||
return true;
|
||||
}
|
||||
$rs = dcCore::app()->log->getLogs([
|
||||
'log_table' => My::id() . '_report',
|
||||
]);
|
||||
|
||||
$time = date('U', $time);
|
||||
if (!is_numeric($time) || (int) $time + self::EXPIRED_DELAY < time()) {
|
||||
return true;
|
||||
}
|
||||
return $rs->isEmpty() || !is_string($rs->f('log_msg')) ? '' : $rs->f('log_msg');
|
||||
}
|
||||
|
||||
return false;
|
||||
private static function expired(): bool
|
||||
{
|
||||
$rs = dcCore::app()->log->getLogs([
|
||||
'log_table' => My::id() . '_report',
|
||||
]);
|
||||
|
||||
return $rs->isEmpty() || !is_string($rs->f('log_dt')) || (int) Date::str('%s', $rs->f('log_dt')) + self::EXPIRED_DELAY < time();
|
||||
}
|
||||
|
||||
private static function contents(): string
|
||||
{
|
||||
// Build json response
|
||||
return (string) json_encode([
|
||||
'uid' => self::uid(),
|
||||
'buid' => self::buid(),
|
||||
'plugin' => self::getPlugins(), // enabled plugins
|
||||
'theme' => self::getThemes(), // enabled themes
|
||||
'server' => [
|
||||
'blogs_count' => (int) dcCore::app()->getBlogs([], true)->f(0),
|
||||
'core' => DC_VERSION,
|
||||
'php' => phpversion(),
|
||||
'thm' => (string) dcCore::app()->blog->settings->get('system')->get('theme'), // selected theme
|
||||
'uid' => self::uid(),
|
||||
'buid' => self::buid(),
|
||||
'plugins' => self::getPlugins(), // enabled plugins
|
||||
'themes' => self::getThemes(), // enabled themes
|
||||
'blog' => [
|
||||
'lang' => (string) dcCore::app()->blog->settings->get('system')->get('lang'),
|
||||
'theme' => (string) dcCore::app()->blog->settings->get('system')->get('theme'),
|
||||
],
|
||||
'blogs' => [
|
||||
'count' => (int) dcCore::app()->getBlogs([], true)->f(0),
|
||||
],
|
||||
'core' => [
|
||||
'version' => DC_VERSION,
|
||||
],
|
||||
'php' => [
|
||||
'sapi' => php_sapi_name() ?: 'php',
|
||||
'version' => phpversion(),
|
||||
],
|
||||
'system' => [
|
||||
'name' => php_uname('s'),
|
||||
'version' => php_uname('r'),
|
||||
],
|
||||
'database' => [
|
||||
dcCore::app()->con->driver() => dcCore::app()->con->version(),
|
||||
'driver' => dcCore::app()->con->driver(),
|
||||
'version' => dcCore::app()->con->version(),
|
||||
],
|
||||
], JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue