first draft

master
Jean-Christian Paul Denis 2022-12-02 11:18:09 +01:00
commit 06cc847af8
Signed by: JcDenis
GPG Key ID: 1B5B8C5B90B6C951
6 changed files with 365 additions and 0 deletions

139
_admin.php 100644
View File

@ -0,0 +1,139 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
# only superadmin
if (!$core->auth->isSuperAdmin()) {
return null;
}
# admin behaviors
$core->addBehavior('pluginsToolsTabs', ['csvBehaviors', 'pluginsToolsTabs']);
$core->addBehavior('themesToolsTabs', ['csvBehaviors', 'themesToolsTabs']);
class csvBehaviors
{
# admin plugins page tab
public static function pluginsToolsTabs(dcCore $core): void
{
self::modulesToolsTabs($core, $core->plugins, explode(',', DC_DISTRIB_PLUGINS), $core->adminurl->get('admin.plugins') . '#csv');
}
# admin themes page tab
public static function themesToolsTabs(dcCore $core): void
{
self::modulesToolsTabs($core, $core->themes, explode(',', DC_DISTRIB_THEMES), $core->adminurl->get('admin.blog.theme') . '#csv');
}
# generic page tab
protected static function modulesToolsTabs(dcCore $core, dcModules $modules, array $excludes, string $page_url): void
{
$list = [];
foreach (array_merge($modules->getModules(), $modules->getDisabledModules()) as $id => $module) {
if (!in_array($id, $excludes)) {
$list[$id] = $module;
}
}
echo
'<div class="multi-part" id="csv" title="' . __('Store version') . '">' .
'<h3>' . __('Check store version') . '</h3>';
if (!count($list)) {
echo
'<div class="info">' . __('There is no module to check') . '</div>' .
'</div>';
return;
}
echo
'<form method="post" action="' . $page_url . '" id="csvform">' .
'<p><input type="submit" name="csvcheck" value="' . __('Check lastest store versions') . '" />' .
$core->formNonce() . '</p>' .
'</form>';
if (!empty($_POST['csvcheck'])) {
$store = new csvStore($modules, dcCore::app()->blog->settings->system->store_plugin_url, true);
self::modulesList($list, $store->get(true));
}
echo
'</div>';
}
private static function modulesList($modules, $repos)
{
if (empty($repos)) {
return;
}
echo
'<div class="table-outer">' .
'<table id="mvmodules" class="modules">' .
'<caption class="hidden">' . html::escapeHTML(__('Modules list')) . '</caption><tr>' .
'<th class="first nowrap" colspan="2">' . __('Name') . '</th>' .
'<th class="nowrap count" scope="col">' . __('Current version') . '</th>' .
'<th class="nowrap count" scope="col">' . __('Latest version') . '</th>' .
'<th class="nowrap count" scope="col">' . __('Written for Dotclear') . '</th>';
foreach ($modules as $id => $module) {
$default_icon = false;
if (file_exists($module['root'] . '/icon.svg')) {
$icon = dcPage::getPF($id . '/icon.svg');
} elseif (file_exists($module['root'] . '/icon.png')) {
$icon = dcPage::getPF($id . '/icon.png');
} else {
$icon = 'images/module.svg';
$default_icon = true;
}
if (file_exists($module['root'] . '/icon-dark.svg')) {
$icon = [$icon, dcPage::getPF($id . '/icon-dark.svg')];
} elseif (file_exists($module['root'] . '/icon-dark.png')) {
$icon = [$icon, dcPage::getPF($id . '/icon-dark.png')];
} elseif ($default_icon) {
$icon = [$icon, 'images/module-dark.svg'];
}
echo
'<tr class="line" id="mvmodules_m_' . html::escapeHTML($id) . '">' .
'<td class="module-icon nowrap minimal">' .
dcAdminHelper::adminIcon($icon, false, html::escapeHTML($id), html::escapeHTML($id)) .
'</td>' .
'<th class="module-name nowrap minimal" scope="row">' .
html::escapeHTML($module['name']) . ($id != $module['name'] ? sprintf(__(' (%s)'), $id) : '') .
'</td>';
if (isset($repos[$id])) {
echo
'<td class="module-current-version nowrap count minimal">' . html::escapeHTML($repos[$id]['current_version']) . '</td>' .
'<td class="module-version nowrap count">' . html::escapeHTML($repos[$id]['version']) . '</td>' .
'<td class="module-version nowrap count">' . html::escapeHTML($repos[$id]['dc_min']) . '</td>';
} else {
echo
'<td class="module-current-version nowrap count minimal">' . html::escapeHTML($module['version']) . '</td>' .
'<td class="module-version nowrap count" colspan="2">' . html::escapeHTML(__('No version available on store')) . '</td>';
}
echo
'</tr>';
}
echo
'</table></div>';
}
}

30
_define.php 100644
View File

@ -0,0 +1,30 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_RC_PATH')) {
return null;
}
$this->registerModule(
'Check store version',
'Check plugins and themes available version before update',
'Jean-Christian Denis and Contributors',
'0.1-dev',
[
'requires' => [['core', '2.19']],
'permissions' => null,
'type' => 'plugin',
'support' => 'https://github.com/JcDenis/checkStoreVersion',
'details' => 'https://plugins.dotaddict.org/dc2/details/checkStoreVersion',
'repository' => 'https://raw.githubusercontent.com/JcDenis/checkStoreVersion/master/'
]
);

19
_prepend.php 100644
View File

@ -0,0 +1,19 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_RC_PATH')) {
return null;
}
$__autoload['csvStore'] = dirname(__FILE__) . '/inc/class.csv.store.php';
$__autoload['csvStoreReader'] = dirname(__FILE__) . '/inc/class.csv.store.reader.php';
$__autoload['csvStoreParser'] = dirname(__FILE__) . '/inc/class.csv.store.parser.php';

View File

@ -0,0 +1,57 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_RC_PATH')) {
return null;
}
class csvStoreParser extends dcStoreParser
{
# overwrite dcStoreParser to bypasse current dotclear version
protected function _parse()
{
if (empty($this->xml->module)) {
return;
}
foreach ($this->xml->module as $i) {
$attrs = $i->attributes();
$item = [];
# DC/DA shared markers
$item['id'] = (string) $attrs['id'];
$item['file'] = (string) $i->file;
$item['label'] = (string) $i->name; // deprecated
$item['name'] = (string) $i->name;
$item['version'] = (string) $i->version;
$item['author'] = (string) $i->author;
$item['desc'] = (string) $i->desc;
# DA specific markers
$item['dc_min'] = (string) $i->children(self::$bloc)->dcmin;
$item['details'] = (string) $i->children(self::$bloc)->details;
$item['section'] = (string) $i->children(self::$bloc)->section;
$item['support'] = (string) $i->children(self::$bloc)->support;
$item['sshot'] = (string) $i->children(self::$bloc)->sshot;
$tags = [];
foreach ($i->children(self::$bloc)->tags as $t) {
$tags[] = (string) $t->tag;
}
$item['tags'] = implode(', ', $tags);
# No more filters here, return all modules
$this->items[$item['id']] = $item;
}
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_RC_PATH')) {
return null;
}
class csvStore extends dcStore
{
# overwrite dcStore::check to remove cache and use csvStoreReader and check disabled modules
public function check($force = true)
{
if (!$this->xml_url) {
return false;
}
try {
$parser = DC_STORE_NOT_UPDATE ? false : csvStoreReader::quickParse($this->xml_url, DC_TPL_CACHE, $force);
} catch (Exception $e) {
return false;
}
$raw_datas = !$parser ? [] : $parser->getModules();
uasort($raw_datas, fn ($a, $b) => strtolower($a['id']) <=> strtolower($b['id']));
$updates = [];
$current = array_merge($this->modules->getModules(), $this->modules->getDisabledModules());
foreach ($current as $p_id => $p_infos) {
# non privileged user has no info
if (!is_array($p_infos)) {
continue;
}
# main repository
if (isset($raw_datas[$p_id])) {
if (dcUtils::versionsCompare($raw_datas[$p_id]['version'], $p_infos['version'], '>=')) {
$updates[$p_id] = $raw_datas[$p_id];
$updates[$p_id]['root'] = $p_infos['root'];
$updates[$p_id]['root_writable'] = $p_infos['root_writable'];
$updates[$p_id]['current_version'] = $p_infos['version'];
}
unset($raw_datas[$p_id]);
}
# per module third-party repository
if (!empty($p_infos['repository']) && DC_ALLOW_REPOSITORIES) {
try {
$dcs_url = substr($p_infos['repository'], -12, 12) == '/dcstore.xml' ? $p_infos['repository'] : http::concatURL($p_infos['repository'], 'dcstore.xml');
$dcs_parser = csvStoreReader::quickParse($dcs_url, DC_TPL_CACHE, $force);
if ($dcs_parser !== false) {
$dcs_raw_datas = $dcs_parser->getModules();
if (isset($dcs_raw_datas[$p_id]) && dcUtils::versionsCompare($dcs_raw_datas[$p_id]['version'], $p_infos['version'], '>=')) {
if (!isset($updates[$p_id]) || dcUtils::versionsCompare($dcs_raw_datas[$p_id]['version'], $updates[$p_id]['version'], '>=')) {
$dcs_raw_datas[$p_id]['repository'] = true;
$updates[$p_id] = $dcs_raw_datas[$p_id];
$updates[$p_id]['root'] = $p_infos['root'];
$updates[$p_id]['root_writable'] = $p_infos['root_writable'];
$updates[$p_id]['current_version'] = $p_infos['version'];
}
}
}
} catch (Exception $e) {
}
}
}
$this->data = [
'new' => $raw_datas,
'update' => $updates,
];
return true;
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* @brief checkStoreVersion, 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
*/
if (!defined('DC_RC_PATH')) {
return null;
}
class csvStoreReader extends dcStoreReader
{
# overwrite dcStoreReader to remove cache and use mvStoreParser
public function parse($url)
{
$this->validators = [];
if (!$this->getModulesXML($url) || $this->getStatus() != '200') {
return false;
}
return new csvStoreParser($this->getContent());
}
# overwrite dcStoreReader to remove cache and use mvStoreParser
public static function quickParse($url, $cache_dir = null, $force = true)
{
$parser = new self();
return $parser->parse($url);
}
}