2021-08-26 22:38:34 +00:00
|
|
|
<?php
|
2021-09-27 22:41:10 +00:00
|
|
|
/**
|
|
|
|
* @brief tweakStores, a plugin for Dotclear 2
|
2021-11-04 22:18:43 +00:00
|
|
|
*
|
2021-09-27 22:41:10 +00:00
|
|
|
* @package Dotclear
|
|
|
|
* @subpackage Plugin
|
2021-11-04 22:18:43 +00:00
|
|
|
*
|
2021-09-27 22:41:10 +00:00
|
|
|
* @author Jean-Christian Denis and Contributors
|
2021-11-04 22:18:43 +00:00
|
|
|
*
|
2021-09-27 22:41:10 +00:00
|
|
|
* @copyright Jean-Christian Denis
|
|
|
|
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
|
|
|
*/
|
2023-01-06 08:31:44 +00:00
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Dotclear\Plugin\tweakStores;
|
|
|
|
|
|
|
|
/* clearbricks ns */
|
|
|
|
use files;
|
|
|
|
use text;
|
|
|
|
use xmlTag;
|
|
|
|
|
|
|
|
/* php ns */
|
|
|
|
use DOMDocument;
|
|
|
|
use Exception;
|
|
|
|
|
|
|
|
class Core
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
2021-11-08 21:36:38 +00:00
|
|
|
/** @var array List of notice messages */
|
2021-08-26 22:38:34 +00:00
|
|
|
public static $notice = [];
|
2021-11-08 21:36:38 +00:00
|
|
|
|
|
|
|
/** @var array List of failed messages */
|
2021-08-26 22:38:34 +00:00
|
|
|
public static $failed = [];
|
|
|
|
|
|
|
|
# taken from lib.moduleslist.php
|
2021-11-08 21:36:38 +00:00
|
|
|
public static function sanitizeModule(string $id, array $module): array
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
|
|
|
$label = empty($module['label']) ? $id : $module['label'];
|
|
|
|
$name = __(empty($module['name']) ? $label : $module['name']);
|
2021-11-04 22:18:43 +00:00
|
|
|
$oname = empty($module['name']) ? $label : $module['name'];
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
return array_merge(
|
|
|
|
# Default values
|
|
|
|
[
|
|
|
|
'desc' => '',
|
|
|
|
'author' => '',
|
|
|
|
'version' => 0,
|
|
|
|
'current_version' => 0,
|
|
|
|
'root' => '',
|
|
|
|
'root_writable' => false,
|
|
|
|
'permissions' => null,
|
|
|
|
'parent' => null,
|
|
|
|
'priority' => 1000,
|
|
|
|
'standalone_config' => false,
|
|
|
|
'support' => '',
|
|
|
|
'section' => '',
|
|
|
|
'tags' => '',
|
|
|
|
'details' => '',
|
|
|
|
'sshot' => '',
|
|
|
|
'score' => 0,
|
|
|
|
'type' => null,
|
2021-09-25 19:13:56 +00:00
|
|
|
'requires' => [],
|
2021-08-26 22:38:34 +00:00
|
|
|
'settings' => [],
|
|
|
|
'repository' => '',
|
2022-11-14 22:52:56 +00:00
|
|
|
'dc_min' => 0,
|
2021-08-26 22:38:34 +00:00
|
|
|
],
|
|
|
|
# Module's values
|
|
|
|
$module,
|
|
|
|
# Clean up values
|
|
|
|
[
|
|
|
|
'id' => $id,
|
|
|
|
'sid' => self::sanitizeString($id),
|
|
|
|
'label' => $label,
|
|
|
|
'name' => $name,
|
2021-09-25 19:13:56 +00:00
|
|
|
'oname' => $oname,
|
2022-11-14 22:52:56 +00:00
|
|
|
'sname' => self::sanitizeString($name),
|
2021-08-26 22:38:34 +00:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
# taken from lib.moduleslist.php
|
2021-11-08 21:36:38 +00:00
|
|
|
public static function sanitizeString(string $str): string
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
2021-11-08 21:36:38 +00:00
|
|
|
return (string) preg_replace('/[^A-Za-z0-9\@\#+_-]/', '', strtolower($str));
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-08 21:36:38 +00:00
|
|
|
public static function parseFilePattern(string $id, array $module, string $file_pattern): string
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
|
|
|
$module = self::sanitizeModule($id, $module);
|
2021-11-04 22:18:43 +00:00
|
|
|
|
2021-08-26 22:38:34 +00:00
|
|
|
return text::tidyURL(str_replace(
|
|
|
|
[
|
|
|
|
'%type%',
|
|
|
|
'%id%',
|
|
|
|
'%version%',
|
2022-11-14 22:52:56 +00:00
|
|
|
'%author%',
|
2021-08-26 22:38:34 +00:00
|
|
|
],
|
|
|
|
[
|
|
|
|
$module['type'],
|
|
|
|
$module['id'],
|
|
|
|
$module['version'],
|
2022-11-14 22:52:56 +00:00
|
|
|
$module['author'],
|
2021-08-26 22:38:34 +00:00
|
|
|
],
|
|
|
|
$file_pattern
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2021-11-08 21:36:38 +00:00
|
|
|
public static function generateXML(string $id, array $module, string $file_pattern): string
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
|
|
|
if (!is_array($module) || empty($module)) {
|
2021-11-08 21:36:38 +00:00
|
|
|
return '';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
$module = self::sanitizeModule($id, $module);
|
2021-11-04 22:18:43 +00:00
|
|
|
$rsp = new xmlTag('module');
|
2021-09-27 22:46:41 +00:00
|
|
|
|
2021-08-26 22:38:34 +00:00
|
|
|
self::$notice = [];
|
|
|
|
self::$failed = [];
|
|
|
|
|
|
|
|
# id
|
|
|
|
if (empty($module['id'])) {
|
|
|
|
self::$failed[] = 'unknow module';
|
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->id = $module['id'];
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# name
|
|
|
|
if (empty($module['name'])) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no module name set in _define.php';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->name($module['oname']);
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# version
|
|
|
|
if (empty($module['version'])) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no module version set in _define.php';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->version($module['version']);
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# author
|
|
|
|
if (empty($module['author'])) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no module author set in _define.php';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->author($module['author']);
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# desc
|
|
|
|
if (empty($module['desc'])) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no module description set in _define.php';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->desc($module['desc']);
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# repository
|
|
|
|
if (empty($module['repository'])) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no repository set in _define.php';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# file
|
|
|
|
$file_pattern = self::parseFilePattern($id, $module, $file_pattern);
|
|
|
|
if (empty($file_pattern)) {
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed[] = 'no zip file pattern set in Tweak Store configuration';
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->file($file_pattern);
|
2021-08-26 22:38:34 +00:00
|
|
|
|
2021-09-25 19:13:56 +00:00
|
|
|
# da dc_min or requires core
|
2021-09-27 22:41:10 +00:00
|
|
|
if (!empty($module['requires']) && is_array($module['requires'])) {
|
2021-09-25 19:13:56 +00:00
|
|
|
foreach ($module['requires'] as $req) {
|
|
|
|
if (!is_array($req)) {
|
|
|
|
$req = [$req];
|
|
|
|
}
|
|
|
|
if ($req[0] == 'core') {
|
|
|
|
$module['dc_min'] = $req[1];
|
2021-11-04 22:18:43 +00:00
|
|
|
|
2021-09-25 19:13:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-26 22:38:34 +00:00
|
|
|
if (empty($module['dc_min'])) {
|
|
|
|
self::$notice[] = 'no minimum dotclear version';
|
2021-09-25 19:13:56 +00:00
|
|
|
} else {
|
2021-09-27 22:41:10 +00:00
|
|
|
$rsp->insertNode(new xmlTag('da:dcmin', $module['dc_min']));
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# details
|
|
|
|
if (empty($module['details'])) {
|
|
|
|
self::$notice[] = 'no details URL';
|
2021-09-27 22:41:10 +00:00
|
|
|
} else {
|
|
|
|
$rsp->insertNode(new xmlTag('da:details', $module['details']));
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
# section
|
2021-09-27 22:41:10 +00:00
|
|
|
if (!empty($module['section'])) {
|
|
|
|
$rsp->insertNode(new xmlTag('da:section', $module['section']));
|
|
|
|
}
|
2021-08-26 22:38:34 +00:00
|
|
|
|
|
|
|
# support
|
|
|
|
if (empty($module['support'])) {
|
|
|
|
self::$notice[] = 'no support URL';
|
2021-09-27 22:41:10 +00:00
|
|
|
} else {
|
|
|
|
$rsp->insertNode(new xmlTag('da:support', $module['support']));
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
2021-09-27 22:41:10 +00:00
|
|
|
$res = new xmlTag('modules', $rsp);
|
|
|
|
$res->insertAttr('xmlns:da', 'http://dotaddict.org/da/');
|
2021-08-26 22:38:34 +00:00
|
|
|
|
2021-11-06 14:37:56 +00:00
|
|
|
return self::prettyXML($res->toXML());
|
2021-08-26 22:38:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-08 21:36:38 +00:00
|
|
|
public static function writeXML(string $id, array $module, string $file_pattern): bool
|
2021-08-26 22:38:34 +00:00
|
|
|
{
|
2021-08-27 09:47:27 +00:00
|
|
|
self::$failed = [];
|
2021-08-26 22:38:34 +00:00
|
|
|
if (!$module['root_writable']) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$content = self::generateXML($id, $module, $file_pattern);
|
|
|
|
if (!empty(self::$failed)) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-04 22:18:43 +00:00
|
|
|
|
2021-08-26 22:38:34 +00:00
|
|
|
try {
|
2021-11-06 14:37:56 +00:00
|
|
|
files::putContent($module['root'] . '/dcstore.xml', $content);
|
2021-11-04 22:18:43 +00:00
|
|
|
} catch (Exception $e) {
|
2021-08-26 22:38:34 +00:00
|
|
|
self::$failed[] = $e->getMessage();
|
2021-11-04 22:18:43 +00:00
|
|
|
|
2021-08-26 22:38:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-11-04 22:18:43 +00:00
|
|
|
|
2021-08-26 22:38:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
2021-11-06 14:37:56 +00:00
|
|
|
|
|
|
|
public static function prettyXML(string $str): string
|
|
|
|
{
|
|
|
|
if (class_exists('DOMDocument')) {
|
|
|
|
$dom = new DOMDocument('1.0');
|
|
|
|
$dom->preserveWhiteSpace = false;
|
|
|
|
$dom->formatOutput = true;
|
|
|
|
$dom->loadXML($str);
|
|
|
|
|
2021-11-08 21:36:38 +00:00
|
|
|
return (string) $dom->saveXML();
|
2021-11-06 14:37:56 +00:00
|
|
|
}
|
|
|
|
|
2021-11-08 21:36:38 +00:00
|
|
|
return (string) str_replace('><', ">\n<", $str);
|
2021-11-06 14:37:56 +00:00
|
|
|
}
|
2021-11-04 22:18:43 +00:00
|
|
|
}
|