update to latest dotclear 2.26-dev changes
This commit is contained in:
parent
cd5b62be60
commit
465b397504
6 changed files with 152 additions and 232 deletions
|
@ -88,11 +88,11 @@ class Config extends dcNsProcess
|
||||||
$img_off = sprintf($img, __('not writable'), 'check-off.png');
|
$img_off = sprintf($img, __('not writable'), 'check-off.png');
|
||||||
|
|
||||||
$repo = Utils::getRepositoryDir($s->pack_repository);
|
$repo = Utils::getRepositoryDir($s->pack_repository);
|
||||||
$check_repo = Utils::is_writable($repo, '_.zip') ? $img_on : $img_off;
|
$check_repo = Utils::isWritable($repo, '_.zip') ? $img_on : $img_off;
|
||||||
$check_first = !empty($s->pack_filename) && Utils::is_writable($repo, $s->pack_filename) ? $img_on : $img_off;
|
$check_first = !empty($s->pack_filename) && Utils::isWritable($repo, $s->pack_filename) ? $img_on : $img_off;
|
||||||
$check_second = !empty($s->secondpack_filename) && Utils::is_writable($repo, $s->secondpack_filename) ? $img_on : $img_off;
|
$check_second = !empty($s->secondpack_filename) && Utils::isWritable($repo, $s->secondpack_filename) ? $img_on : $img_off;
|
||||||
|
|
||||||
$is_configured = Utils::is_configured(
|
$is_configured = Utils::isConfigured(
|
||||||
$repo,
|
$repo,
|
||||||
$s->pack_filename,
|
$s->pack_filename,
|
||||||
$s->secondpack_filename
|
$s->secondpack_filename
|
||||||
|
|
122
src/Core.php
122
src/Core.php
|
@ -15,10 +15,11 @@ declare(strict_types=1);
|
||||||
namespace Dotclear\Plugin\pacKman;
|
namespace Dotclear\Plugin\pacKman;
|
||||||
|
|
||||||
use dcCore;
|
use dcCore;
|
||||||
|
use dcModuleDefine;
|
||||||
use dcModules;
|
use dcModules;
|
||||||
use files;
|
use Dotclear\Helper\File\Files;
|
||||||
|
use Dotclear\Helper\File\Path;
|
||||||
use Dotclear\Helper\File\Zip\Unzip;
|
use Dotclear\Helper\File\Zip\Unzip;
|
||||||
use path;
|
|
||||||
|
|
||||||
class Core
|
class Core
|
||||||
{
|
{
|
||||||
|
@ -39,12 +40,11 @@ class Core
|
||||||
{
|
{
|
||||||
$res = [];
|
$res = [];
|
||||||
|
|
||||||
$cache = self::getCache() . DIRECTORY_SEPARATOR;
|
|
||||||
if (!is_dir($root) || !is_readable($root)) {
|
if (!is_dir($root) || !is_readable($root)) {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
$files = files::scanDir($root);
|
$files = Files::scanDir($root);
|
||||||
$zip_files = [];
|
$zip_files = [];
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
if (!preg_match('#(^|/)(.*?)\.zip(/|$)#', $file)) {
|
if (!preg_match('#(^|/)(.*?)\.zip(/|$)#', $file)) {
|
||||||
|
@ -95,7 +95,7 @@ class Core
|
||||||
|
|
||||||
foreach ($sandboxes as $type => $sandbox) {
|
foreach ($sandboxes as $type => $sandbox) {
|
||||||
try {
|
try {
|
||||||
files::makeDir($path, true);
|
Files::makeDir($path, true);
|
||||||
|
|
||||||
// can't load twice _init.php file !
|
// can't load twice _init.php file !
|
||||||
$unlink = false;
|
$unlink = false;
|
||||||
|
@ -118,14 +118,14 @@ class Core
|
||||||
if (!$sandbox->getErrors()) {
|
if (!$sandbox->getErrors()) {
|
||||||
$module = $sandbox->getDefine(basename($path));
|
$module = $sandbox->getDefine(basename($path));
|
||||||
if ($module->isDefined() && $module->get('type') == $type) {
|
if ($module->isDefined() && $module->get('type') == $type) {
|
||||||
$res[$i] = $module->dump();
|
$res[$i] = $module;
|
||||||
$res[$i]['root'] = $zip_file;
|
$res[$i]->set('root', $zip_file);
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
}
|
}
|
||||||
files::deltree($path);
|
Files::deltree($path);
|
||||||
}
|
}
|
||||||
$zip->close();
|
$zip->close();
|
||||||
}
|
}
|
||||||
|
@ -133,20 +133,34 @@ class Core
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function pack(array $info, string $root, array $files, bool $overwrite = false, array $exclude = [], bool $nocomment = false, bool $fixnewline = false): bool
|
public static function pack(dcModuleDefine $define, string $root, array $files, bool $overwrite = false, array $exclude = [], bool $nocomment = false, bool $fixnewline = false): bool
|
||||||
{
|
{
|
||||||
if (!($info = self::getInfo($info))
|
// check define
|
||||||
|| !($root = self::getRoot($root))
|
if (!$define->isDefined()
|
||||||
|
|| empty($define->get('root'))
|
||||||
|
|| !is_dir($define->get('root'))
|
||||||
) {
|
) {
|
||||||
return false;
|
throw new Exception(__('Failed to get module info'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$exclude = self::getExclude($exclude);
|
// check root
|
||||||
|
$root = (string) Path::real($root);
|
||||||
|
if (!is_dir($root) || !is_writable($root)) {
|
||||||
|
throw new Exception(__('Directory is not writable'));
|
||||||
|
}
|
||||||
|
|
||||||
|
//set excluded
|
||||||
|
$exclude = self::quote_exclude(array_merge(My::EXCLUDED_FILES, $exclude));
|
||||||
|
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
if (!($file = self::getFile($file, $info))
|
if (empty($file)) {
|
||||||
|| !($dest = self::getOverwrite($overwrite, $root, $file))
|
continue;
|
||||||
) {
|
}
|
||||||
|
|
||||||
|
// check path
|
||||||
|
$path = $root . DIRECTORY_SEPARATOR . self::getFile($file, $define);
|
||||||
|
if (file_exists($path) && !$overwrite) {
|
||||||
|
// don't break loop
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,14 +172,14 @@ class Core
|
||||||
if ($fixnewline) {
|
if ($fixnewline) {
|
||||||
Zip::$fix_newline = true;
|
Zip::$fix_newline = true;
|
||||||
}
|
}
|
||||||
$zip = new Zip($dest);
|
$zip = new Zip($path);
|
||||||
|
|
||||||
foreach ($exclude as $e) {
|
foreach ($exclude as $e) {
|
||||||
$zip->addExclusion($e);
|
$zip->addExclusion($e);
|
||||||
}
|
}
|
||||||
$zip->addDirectory(
|
$zip->addDirectory(
|
||||||
(string) path::real($info['root'], false),
|
(string) Path::real($define->get('root'), false),
|
||||||
$info['id'],
|
$define->getId(),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -176,41 +190,8 @@ class Core
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getRoot(string $root): string
|
private static function getFile(string $file, dcModuleDefine $define): string
|
||||||
{
|
{
|
||||||
$root = (string) path::real($root);
|
|
||||||
if (!is_dir($root) || !is_writable($root)) {
|
|
||||||
throw new Exception(__('Directory is not writable'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $root;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function getInfo(array $info): array
|
|
||||||
{
|
|
||||||
if (!isset($info['root'])
|
|
||||||
|| !isset($info['id'])
|
|
||||||
|| !is_dir($info['root'])
|
|
||||||
) {
|
|
||||||
throw new Exception(__('Failed to get module info'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function getExclude(array $exclude): array
|
|
||||||
{
|
|
||||||
$exclude = array_merge(My::EXCLUDED_FILES, $exclude);
|
|
||||||
|
|
||||||
return self::quote_exclude($exclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function getFile(string $file, array $info): ?string
|
|
||||||
{
|
|
||||||
if (empty($file) || empty($info)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = str_replace(
|
$file = str_replace(
|
||||||
[
|
[
|
||||||
'\\',
|
'\\',
|
||||||
|
@ -222,44 +203,19 @@ class Core
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'/',
|
'/',
|
||||||
$info['type'],
|
$define->get('type'),
|
||||||
$info['id'],
|
$define->getId(),
|
||||||
$info['version'],
|
$define->get('version'),
|
||||||
$info['author'],
|
$define->get('author'),
|
||||||
time(),
|
time(),
|
||||||
],
|
],
|
||||||
$file
|
$file
|
||||||
);
|
);
|
||||||
$parts = explode('/', $file);
|
$parts = explode('/', $file);
|
||||||
foreach ($parts as $i => $part) {
|
foreach ($parts as $i => $part) {
|
||||||
$parts[$i] = files::tidyFileName($part);
|
$parts[$i] = Files::tidyFileName($part);
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(DIRECTORY_SEPARATOR, $parts) . '.zip';
|
return implode(DIRECTORY_SEPARATOR, $parts) . '.zip';
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getOverwrite(bool $overwrite, string $root, string$file): ?string
|
|
||||||
{
|
|
||||||
$path = $root . DIRECTORY_SEPARATOR . $file;
|
|
||||||
if (file_exists($path) && !$overwrite) {
|
|
||||||
// don't break loop
|
|
||||||
//throw new Exception('File already exists');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function getCache(): string
|
|
||||||
{
|
|
||||||
$c = DC_TPL_CACHE . DIRECTORY_SEPARATOR . 'packman';
|
|
||||||
if (!file_exists($c)) {
|
|
||||||
@files::makeDir($c);
|
|
||||||
}
|
|
||||||
if (!is_writable($c)) {
|
|
||||||
throw new Exception(__('Failed to get temporary directory'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,13 +59,13 @@ class Install extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
while ($record->fetch()) {
|
while ($record->fetch()) {
|
||||||
if (preg_match('/^packman_(.*?)$/', $record->setting_id, $match)) {
|
if (preg_match('/^packman_(.*?)$/', $record->f('setting_id'), $match)) {
|
||||||
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
|
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
|
||||||
$cur->setting_id = $match[1];
|
$cur->setField('setting_id', $match[1]);
|
||||||
$cur->setting_ns = My::id();
|
$cur->setField('setting_ns', My::id());
|
||||||
$cur->update(
|
$cur->update(
|
||||||
"WHERE setting_id = '" . $record->setting_id . "' and setting_ns = 'pacKman' " .
|
"WHERE setting_id = '" . $record->f('setting_id') . "' and setting_ns = 'pacKman' " .
|
||||||
'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escape($record->blog_id) . "' "))
|
'AND blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ("= '" . dcCore::app()->con->escapeStr($record->f('blog_id')) . "' "))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,8 @@ use dcCore;
|
||||||
use dcPage;
|
use dcPage;
|
||||||
use dcThemes;
|
use dcThemes;
|
||||||
use dcNsProcess;
|
use dcNsProcess;
|
||||||
|
use Dotclear\Helper\File\Files;
|
||||||
/* clearbricks ns */
|
use Dotclear\Helper\Network\Http;
|
||||||
use files;
|
|
||||||
use http;
|
|
||||||
|
|
||||||
class Manage extends dcNsProcess
|
class Manage extends dcNsProcess
|
||||||
{
|
{
|
||||||
|
@ -58,13 +56,8 @@ class Manage extends dcNsProcess
|
||||||
$plugins = dcCore::app()->plugins;
|
$plugins = dcCore::app()->plugins;
|
||||||
|
|
||||||
# Rights
|
# Rights
|
||||||
$is_writable = Utils::is_writable(
|
$is_writable = Utils::isWritable($dir, $s->pack_filename);
|
||||||
$dir,
|
$is_editable = !empty($type) && !empty($_POST['modules']) && is_array($_POST['modules']);
|
||||||
$s->pack_filename
|
|
||||||
);
|
|
||||||
$is_editable = !empty($type)
|
|
||||||
&& !empty($_POST['modules'])
|
|
||||||
&& is_array($_POST['modules']);
|
|
||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
try {
|
try {
|
||||||
|
@ -77,25 +70,25 @@ class Manage extends dcNsProcess
|
||||||
$modules = Core::getPackages(Utils::getThemesPath());
|
$modules = Core::getPackages(Utils::getThemesPath());
|
||||||
} else {
|
} else {
|
||||||
$modules = array_merge(
|
$modules = array_merge(
|
||||||
Core::getPackages(dirname($dir . '/' . $s->pack_filename)),
|
Core::getPackages(dirname($dir . DIRECTORY_SEPARATOR . $s->pack_filename)),
|
||||||
Core::getPackages(dirname($dir . '/' . $s->secondpack_filename))
|
Core::getPackages(dirname($dir . DIRECTORY_SEPARATOR . $s->secondpack_filename))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($modules as $f) {
|
foreach ($modules as $module) {
|
||||||
if (preg_match('/' . preg_quote($_REQUEST['package']) . '$/', $f['root'])
|
if (preg_match('/' . preg_quote($_REQUEST['package']) . '$/', $module->get('root'))
|
||||||
&& is_file($f['root']) && is_readable($f['root'])
|
&& is_file($module->get('root')) && is_readable($module->get('root'))
|
||||||
) {
|
) {
|
||||||
# --BEHAVIOR-- packmanBeforeDownloadPackage
|
# --BEHAVIOR-- packmanBeforeDownloadPackage
|
||||||
dcCore::app()->callBehavior('packmanBeforeDownloadPackage', $f, $type);
|
dcCore::app()->callBehavior('packmanBeforeDownloadPackage', $module->dump(), $type);
|
||||||
|
|
||||||
header('Content-Type: application/zip');
|
header('Content-Type: application/zip');
|
||||||
header('Content-Length: ' . filesize($f['root']));
|
header('Content-Length: ' . filesize($module->get('root')));
|
||||||
header('Content-Disposition: attachment; filename="' . basename($f['root']) . '"');
|
header('Content-Disposition: attachment; filename="' . basename($module->get('root')) . '"');
|
||||||
readfile($f['root']);
|
readfile($module->get('root'));
|
||||||
|
|
||||||
# --BEHAVIOR-- packmanAfterDownloadPackage
|
# --BEHAVIOR-- packmanAfterDownloadPackage
|
||||||
dcCore::app()->callBehavior('packmanAfterDownloadPackage', $f, $type);
|
dcCore::app()->callBehavior('packmanAfterDownloadPackage', $module->dump(), $type);
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +96,7 @@ class Manage extends dcNsProcess
|
||||||
|
|
||||||
# Not found
|
# Not found
|
||||||
header('Content-Type: text/plain');
|
header('Content-Type: text/plain');
|
||||||
http::head(404, 'Not Found');
|
Http::head(404, 'Not Found');
|
||||||
exit;
|
exit;
|
||||||
} elseif (!empty($action) && !$is_editable) {
|
} elseif (!empty($action) && !$is_editable) {
|
||||||
dcPage::addErrorNotice(
|
dcPage::addErrorNotice(
|
||||||
|
@ -111,7 +104,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -119,16 +112,14 @@ class Manage extends dcNsProcess
|
||||||
# Pack
|
# Pack
|
||||||
} elseif ($action == 'packup') {
|
} elseif ($action == 'packup') {
|
||||||
foreach ($_POST['modules'] as $root => $id) {
|
foreach ($_POST['modules'] as $root => $id) {
|
||||||
if (!Utils::moduleExists($type, $id)) {
|
if (!dcCore::app()->{$type}->getDefine($id)->isDefined()) {
|
||||||
throw new Exception('No such module');
|
throw new Exception('No such module');
|
||||||
}
|
}
|
||||||
|
|
||||||
$module = Utils::getModules($type, $id);
|
$module = dcCore::app()->{$type}->getDefine($id);
|
||||||
$module['id'] = $id;
|
|
||||||
$module['type'] = $type == 'themes' ? 'theme' : 'plugin';
|
|
||||||
|
|
||||||
# --BEHAVIOR-- packmanBeforeCreatePackage
|
# --BEHAVIOR-- packmanBeforeCreatePackage
|
||||||
dcCore::app()->callBehavior('packmanBeforeCreatePackage', $module);
|
dcCore::app()->callBehavior('packmanBeforeCreatePackage', $module->dump());
|
||||||
|
|
||||||
Core::pack(
|
Core::pack(
|
||||||
$module,
|
$module,
|
||||||
|
@ -141,7 +132,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
# --BEHAVIOR-- packmanAfterCreatePackage
|
# --BEHAVIOR-- packmanAfterCreatePackage
|
||||||
dcCore::app()->callBehavior('packmanAfterCreatePackage', $module);
|
dcCore::app()->callBehavior('packmanAfterCreatePackage', $module->dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
dcPage::addSuccessNotice(
|
dcPage::addSuccessNotice(
|
||||||
|
@ -149,7 +140,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +149,7 @@ class Manage extends dcNsProcess
|
||||||
} elseif ($action == 'delete') {
|
} elseif ($action == 'delete') {
|
||||||
$del_success = false;
|
$del_success = false;
|
||||||
foreach ($_POST['modules'] as $root => $id) {
|
foreach ($_POST['modules'] as $root => $id) {
|
||||||
if (!file_exists($root) || !files::isDeletable($root)) {
|
if (!file_exists($root) || !Files::isDeletable($root)) {
|
||||||
dcPage::addWarningNotice(sprintf(__('Undeletable file "%s"', $root)));
|
dcPage::addWarningNotice(sprintf(__('Undeletable file "%s"', $root)));
|
||||||
} else {
|
} else {
|
||||||
$del_success = true;
|
$del_success = true;
|
||||||
|
@ -174,7 +165,7 @@ class Manage extends dcNsProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +192,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -217,7 +208,7 @@ class Manage extends dcNsProcess
|
||||||
|
|
||||||
foreach ($_POST['modules'] as $root => $id) {
|
foreach ($_POST['modules'] as $root => $id) {
|
||||||
file_put_contents(
|
file_put_contents(
|
||||||
$dest . '/' . basename($root),
|
$dest . DIRECTORY_SEPARATOR . basename($root),
|
||||||
file_get_contents($root)
|
file_get_contents($root)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +218,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +245,7 @@ class Manage extends dcNsProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!empty($_POST['redir'])) {
|
if (!empty($_POST['redir'])) {
|
||||||
http::redirect($_POST['redir']);
|
Http::redirect($_POST['redir']);
|
||||||
} else {
|
} else {
|
||||||
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id(), [], '#packman-repository-' . $type);
|
||||||
}
|
}
|
||||||
|
@ -276,7 +267,7 @@ class Manage extends dcNsProcess
|
||||||
$s = new Settings();
|
$s = new Settings();
|
||||||
$dir = Utils::getRepositoryDir($s->pack_repository);
|
$dir = Utils::getRepositoryDir($s->pack_repository);
|
||||||
|
|
||||||
$is_configured = Utils::is_configured(
|
$is_configured = Utils::isConfigured(
|
||||||
$dir,
|
$dir,
|
||||||
$s->pack_filename,
|
$s->pack_filename,
|
||||||
$s->secondpack_filename
|
$s->secondpack_filename
|
||||||
|
@ -306,13 +297,13 @@ class Manage extends dcNsProcess
|
||||||
'</div>';
|
'</div>';
|
||||||
} else {
|
} else {
|
||||||
Utils::modules(
|
Utils::modules(
|
||||||
Utils::getModules('plugins'),
|
dcCore::app()->plugins->getDefines((new Settings())->hide_distrib ? ['distributed' => false] : []),
|
||||||
'plugins',
|
'plugins',
|
||||||
__('Installed plugins')
|
__('Installed plugins')
|
||||||
);
|
);
|
||||||
|
|
||||||
Utils::modules(
|
Utils::modules(
|
||||||
Utils::getModules('themes'),
|
dcCore::app()->themes->getDefines((new Settings())->hide_distrib ? ['distributed' => false] : []),
|
||||||
'themes',
|
'themes',
|
||||||
__('Installed themes')
|
__('Installed themes')
|
||||||
);
|
);
|
||||||
|
@ -331,8 +322,8 @@ class Manage extends dcNsProcess
|
||||||
|
|
||||||
Utils::repository(
|
Utils::repository(
|
||||||
array_merge(
|
array_merge(
|
||||||
Core::getPackages(dirname($dir . '/' . $s->pack_filename)),
|
Core::getPackages(dirname($dir . DIRECTORY_SEPARATOR . $s->pack_filename)),
|
||||||
Core::getPackages(dirname($dir . '/' . $s->secondpack_filename))
|
Core::getPackages(dirname($dir . DIRECTORY_SEPARATOR . $s->secondpack_filename))
|
||||||
),
|
),
|
||||||
'repository',
|
'repository',
|
||||||
__('Packages repository')
|
__('Packages repository')
|
||||||
|
|
|
@ -20,14 +20,14 @@ class Uninstall
|
||||||
|
|
||||||
public static function init(): bool
|
public static function init(): bool
|
||||||
{
|
{
|
||||||
self::$init = defined('DC_RC_PATH');
|
static::$init = defined('DC_RC_PATH');
|
||||||
|
|
||||||
return self::$init;
|
return static::$init;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function process($uninstaller): ?bool
|
public static function process($uninstaller): ?bool
|
||||||
{
|
{
|
||||||
if (!self::$init) {
|
if (!static::$init) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
163
src/Utils.php
163
src/Utils.php
|
@ -14,17 +14,23 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Dotclear\Plugin\pacKman;
|
namespace Dotclear\Plugin\pacKman;
|
||||||
|
|
||||||
/* dotclear ns */
|
|
||||||
use dcCore;
|
use dcCore;
|
||||||
|
use Dotclear\Helper\File\Files;
|
||||||
|
use Dotclear\Helper\File\Path;
|
||||||
use Dotclear\Helper\File\Zip\Unzip;
|
use Dotclear\Helper\File\Zip\Unzip;
|
||||||
use Dotclear\Helper\File\Zip\Zip;
|
use Dotclear\Helper\File\Zip\Zip;
|
||||||
|
use Dotclear\Helper\Html\Form\{
|
||||||
|
Checkbox,
|
||||||
|
Hidden,
|
||||||
|
Label,
|
||||||
|
Para,
|
||||||
|
Select,
|
||||||
|
Submit,
|
||||||
|
Text
|
||||||
|
};
|
||||||
|
use Dotclear\Helper\Html\Html;
|
||||||
|
|
||||||
/* clearbricks ns */
|
|
||||||
use dt;
|
use dt;
|
||||||
use files;
|
|
||||||
use form;
|
|
||||||
use html;
|
|
||||||
use path;
|
|
||||||
|
|
||||||
class Utils
|
class Utils
|
||||||
{
|
{
|
||||||
|
@ -33,7 +39,7 @@ class Utils
|
||||||
$e = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT);
|
$e = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT);
|
||||||
$p = array_pop($e);
|
$p = array_pop($e);
|
||||||
|
|
||||||
return (string) path::real($p);
|
return (string) Path::real($p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getThemesPath(): string
|
public static function getThemesPath(): string
|
||||||
|
@ -41,13 +47,8 @@ class Utils
|
||||||
return (string) dcCore::app()->blog?->themes_path;
|
return (string) dcCore::app()->blog?->themes_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function is_configured(string $repo, string $file_a, string $file_b): bool
|
public static function isConfigured(string $repo, string $file_a, string $file_b): bool
|
||||||
{
|
{
|
||||||
if (!is_dir(DC_TPL_CACHE) || !is_writable(DC_TPL_CACHE)) {
|
|
||||||
dcCore::app()->error->add(
|
|
||||||
__('Cache directory is not writable.')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!is_writable($repo)) {
|
if (!is_writable($repo)) {
|
||||||
dcCore::app()->error->add(
|
dcCore::app()->error->add(
|
||||||
__('Path to repository is not writable.')
|
__('Path to repository is not writable.')
|
||||||
|
@ -75,7 +76,7 @@ class Utils
|
||||||
return !dcCore::app()->error->flag();
|
return !dcCore::app()->error->flag();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function is_writable(string $path, string $file): bool
|
public static function isWritable(string $path, string $file): bool
|
||||||
{
|
{
|
||||||
return !(empty($path) || empty($file) || !is_writable(dirname($path . DIRECTORY_SEPARATOR . $file)));
|
return !(empty($path) || empty($file) || !is_writable(dirname($path . DIRECTORY_SEPARATOR . $file)));
|
||||||
}
|
}
|
||||||
|
@ -143,7 +144,7 @@ class Utils
|
||||||
if (empty($dir)) {
|
if (empty($dir)) {
|
||||||
try {
|
try {
|
||||||
$dir = DC_VAR . DIRECTORY_SEPARATOR . 'packman';
|
$dir = DC_VAR . DIRECTORY_SEPARATOR . 'packman';
|
||||||
@files::makeDir($dir, true);
|
@Files::makeDir($dir, true);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$dir = '';
|
$dir = '';
|
||||||
}
|
}
|
||||||
|
@ -152,35 +153,9 @@ class Utils
|
||||||
return $dir;
|
return $dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getModules(string $type, ?string $id = null): array
|
|
||||||
{
|
|
||||||
$type = $type == 'themes' ? 'themes' : 'plugins';
|
|
||||||
|
|
||||||
$modules = array_merge(dcCore::app()->{$type}->getDisabledModules(), dcCore::app()->{$type}->getModules());
|
|
||||||
|
|
||||||
if ((new Settings())->hide_distrib) {
|
|
||||||
$modules = array_diff_key($modules, array_flip(array_values(array_merge(explode(',', DC_DISTRIB_PLUGINS), explode(',', DC_DISTRIB_THEMES)))));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($id)) {
|
|
||||||
return $modules;
|
|
||||||
} elseif (array_key_exists($id, $modules)) {
|
|
||||||
return $modules[$id];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function moduleExists(string $type, ?string $id): bool
|
|
||||||
{
|
|
||||||
$type = $type == 'themes' ? 'themes' : 'plugins';
|
|
||||||
|
|
||||||
return array_key_exists((string) $id, array_merge(dcCore::app()->{$type}->getDisabledModules(), dcCore::app()->{$type}->getModules()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function modules(array $modules, string $type, string $title): ?bool
|
public static function modules(array $modules, string $type, string $title): ?bool
|
||||||
{
|
{
|
||||||
if (empty($modules) || !is_array($modules)) {
|
if (empty($modules)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,42 +173,41 @@ class Utils
|
||||||
'<th class="nowrap">' . __('Root') . '</th>' .
|
'<th class="nowrap">' . __('Root') . '</th>' .
|
||||||
'</tr>';
|
'</tr>';
|
||||||
|
|
||||||
foreach (self::sort($modules) as $id => $module) {
|
$i = 1;
|
||||||
|
self::sort($modules);
|
||||||
|
foreach ($modules as $module) {
|
||||||
echo
|
echo
|
||||||
'<tr class="line">' .
|
'<tr class="line">' .
|
||||||
'<td class="nowrap"><label class="classic">' .
|
(new Para(null, 'td'))->class('nowrap')->items([
|
||||||
form::checkbox(['modules[' . html::escapeHTML($module['root']) . ']'], html::escapeHTML($id)) .
|
(new Checkbox(['modules[' . Html::escapeHTML($module->get('root')) . ']', 'modules_' . $type . $i], false))->value(Html::escapeHTML($module->getId())),
|
||||||
html::escapeHTML($id) .
|
(new Label(Html::escapeHTML($module->getId()), Label::OUTSIDE_LABEL_AFTER))->for('modules_' . $type . $i)->class('classic'),
|
||||||
'</label></td>' .
|
|
||||||
|
])->render() .
|
||||||
'<td class="nowrap count">' .
|
'<td class="nowrap count">' .
|
||||||
html::escapeHTML($module['version']) .
|
Html::escapeHTML($module->get('version')) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'<td class="nowrap maximal">' .
|
'<td class="nowrap maximal">' .
|
||||||
__(html::escapeHTML($module['name'])) .
|
__(Html::escapeHTML($module->get('name'))) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'<td class="nowrap">' .
|
'<td class="nowrap">' .
|
||||||
dirname((string) path::real($module['root'], false)) .
|
dirname((string) Path::real($module->get('root'), false)) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'</tr>';
|
'</tr>';
|
||||||
|
|
||||||
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo
|
echo
|
||||||
'</table>' .
|
'</table>' .
|
||||||
'<p class="checkboxes-helpers"></p>' .
|
'<p class="checkboxes-helpers"></p>' .
|
||||||
'<p>' .
|
(new Para())->items([
|
||||||
(
|
(new Hidden(['redir'], Html::escapeHTML($_REQUEST['redir'] ?? ''))),
|
||||||
!empty($_REQUEST['redir']) ?
|
(new Hidden(['p'], My::id())),
|
||||||
form::hidden(
|
(new Hidden(['type'], $type)),
|
||||||
['redir'],
|
(new Hidden(['action'], 'packup')),
|
||||||
html::escapeHTML($_REQUEST['redir'])
|
(new Submit(['packup']))->value(__('Pack up selected modules')),
|
||||||
) : ''
|
dcCore::app()->formNonce(false),
|
||||||
) .
|
])->render() .
|
||||||
form::hidden(['p'], My::id()) .
|
|
||||||
form::hidden(['type'], $type) .
|
|
||||||
form::hidden(['action'], 'packup') .
|
|
||||||
'<input type="submit" name="packup" value="' .
|
|
||||||
__('Pack up selected modules') . '" />' .
|
|
||||||
dcCore::app()->formNonce() . '</p>' .
|
|
||||||
'</form>' .
|
'</form>' .
|
||||||
|
|
||||||
'</div>';
|
'</div>';
|
||||||
|
@ -243,7 +217,7 @@ class Utils
|
||||||
|
|
||||||
public static function repository(array $modules, string $type, string $title): ?bool
|
public static function repository(array $modules, string $type, string $title): ?bool
|
||||||
{
|
{
|
||||||
if (empty($modules) || !is_array($modules)) {
|
if (empty($modules)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!in_array($type, ['plugins', 'themes', 'repository'])) {
|
if (!in_array($type, ['plugins', 'themes', 'repository'])) {
|
||||||
|
@ -284,52 +258,57 @@ class Utils
|
||||||
'</tr>';
|
'</tr>';
|
||||||
|
|
||||||
$dup = [];
|
$dup = [];
|
||||||
foreach (self::sort($modules) as $module) {
|
$i = 1;
|
||||||
if (isset($dup[$module['root']])) {
|
self::sort($modules);
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
if (isset($dup[$module->get('root')])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dup[$module['root']] = 1;
|
$dup[$module->get('root')] = 1;
|
||||||
|
|
||||||
echo
|
echo
|
||||||
'<tr class="line">' .
|
'<tr class="line">' .
|
||||||
'<td class="nowrap"><label class="classic" title="' .
|
(new Para(null, 'td'))->class('nowrap')->items([
|
||||||
html::escapeHTML($module['root']) . '">' .
|
(new Checkbox(['modules[' . Html::escapeHTML($module->get('root')) . ']', 'r_modules_' . $type . $i], false))->value(Html::escapeHTML($module->getId())),
|
||||||
form::checkbox(['modules[' . html::escapeHTML($module['root']) . ']'], $module['id']) .
|
(new Label(Html::escapeHTML($module->getId()), Label::OUTSIDE_LABEL_AFTER))->for('r_modules_' . $type . $i)->class('classic')->title(Html::escapeHTML($module->get('root'))),
|
||||||
html::escapeHTML($module['id']) .
|
|
||||||
'</label></td>' .
|
])->render() .
|
||||||
'<td class="nowrap count">' .
|
'<td class="nowrap count">' .
|
||||||
html::escapeHTML($module['version']) .
|
Html::escapeHTML($module->get('version')) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'<td class="nowrap maximal">' .
|
'<td class="nowrap maximal">' .
|
||||||
__(html::escapeHTML($module['name'])) .
|
__(Html::escapeHTML($module->get('name'))) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'<td class="nowrap">' .
|
'<td class="nowrap">' .
|
||||||
'<a class="packman-download" href="' .
|
'<a class="packman-download" href="' .
|
||||||
dcCore::app()->adminurl?->get('admin.plugin.' . My::id(), [
|
dcCore::app()->adminurl?->get('admin.plugin.' . My::id(), [
|
||||||
'package' => basename($module['root']),
|
'package' => basename($module->get('root')),
|
||||||
'repo' => $type,
|
'repo' => $type,
|
||||||
]) . '" title="' . __('Download') . '">' .
|
]) . '" title="' . __('Download') . '">' .
|
||||||
html::escapeHTML(basename($module['root'])) . '</a>' .
|
Html::escapeHTML(basename($module->get('root'))) . '</a>' .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'<td class="nowrap">' .
|
'<td class="nowrap">' .
|
||||||
html::escapeHTML(dt::str(__('%Y-%m-%d %H:%M'), (int) @filemtime($module['root']))) .
|
Html::escapeHTML(dt::str(__('%Y-%m-%d %H:%M'), (int) @filemtime($module->get('root')))) .
|
||||||
'</td>' .
|
'</td>' .
|
||||||
'</tr>';
|
'</tr>';
|
||||||
|
|
||||||
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo
|
echo
|
||||||
'</table>' .
|
'</table>' .
|
||||||
'<div class="two-cols">' .
|
'<div class="two-cols">' .
|
||||||
'<p class="col checkboxes-helpers"></p>' .
|
'<p class="col checkboxes-helpers"></p>' .
|
||||||
'<p class="col right">' . __('Selected modules action:') . ' ' .
|
(new Para())->class('col right')->items([
|
||||||
form::combo(['action'], $combo_action) .
|
(new Text('', __('Selected modules action:') . ' ')),
|
||||||
'<input type="submit" name="packup" value="' . __('ok') . '" />' .
|
(new Select(['action']))->items($combo_action),
|
||||||
form::hidden(['p'], My::id()) .
|
(new Submit(['packup']))->value(__('ok')),
|
||||||
form::hidden(['tab'], 'repository') .
|
(new Hidden(['p'], My::id())),
|
||||||
form::hidden(['type'], $type) .
|
(new Hidden(['tab'], 'repository')),
|
||||||
dcCore::app()->formNonce() .
|
(new Hidden(['type'], $type)),
|
||||||
'</p>' .
|
dcCore::app()->formNonce(false),
|
||||||
|
])->render() .
|
||||||
'</div>' .
|
'</div>' .
|
||||||
'</form>' .
|
'</form>' .
|
||||||
'</div>';
|
'</div>';
|
||||||
|
@ -337,15 +316,9 @@ class Utils
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function sort(array $modules): array
|
protected static function sort(array &$modules): void
|
||||||
{
|
{
|
||||||
$key = $ver = [];
|
uasort($modules, fn ($a, $b) => $a->get('version') <=> $b->get('version'));
|
||||||
foreach ($modules as $i => $module) {
|
uasort($modules, fn ($a, $b) => strtolower($a->get('id')) <=> strtolower($b->get('id')));
|
||||||
$key[$i] = $module['id'] ?? $i;
|
|
||||||
$ver[$i] = $module['version'];
|
|
||||||
}
|
|
||||||
array_multisort($key, SORT_ASC, $ver, SORT_ASC, $modules);
|
|
||||||
|
|
||||||
return $modules;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue