Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b13c5b3c8 | ||
|
|
fa464bc20d |
No files matched your search
+1
-1
@@ -14,7 +14,7 @@ composer.phar
|
|||||||
|
|
||||||
# Frontend
|
# Frontend
|
||||||
*.vite/
|
*.vite/
|
||||||
**/public/administration/js/
|
**/public/administration/assets/
|
||||||
**/public/static/js/
|
**/public/static/js/
|
||||||
|
|
||||||
# Environment
|
# Environment
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Requires Shopware 6.7 (`shopware/core ~6.7.0`); 6.6 stays on the 0.0.x line.
|
- Requires Shopware 6.7 (`shopware/core ~6.7.0`); 6.6 stays on the 0.0.x line.
|
||||||
|
- Administration: the list page is registered lazily, uses Meteor components (`mt-button`, `mt-banner`, `mt-progress-bar`) and stops polling on `beforeUnmount` (Vue 3).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The admin build failed on a combined `import type` statement, so the Settings card never appeared.
|
||||||
|
- Creating a dump failed on MariaDB when only MySQL 8's `mysqldump` was installed (`Unknown table 'COLUMN_STATISTICS'`); it now passes `--column-statistics=0` in that case.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ check() { # <label> <entry-glob-prefix> <expected path in zip>
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check admin src/Resources/app/administration/src "Resources/public/administration/js/"
|
check admin src/Resources/app/administration/src "Resources/public/administration/assets/"
|
||||||
check storefront src/Resources/app/storefront/src "Resources/app/storefront/dist/"
|
check storefront src/Resources/app/storefront/src "Resources/app/storefront/dist/"
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import './acl';
|
import './acl';
|
||||||
import './page/aeon-dump-manager-list';
|
|
||||||
import deDE from './snippet/de-DE.json';
|
import deDE from './snippet/de-DE.json';
|
||||||
import enGB from './snippet/en-GB.json';
|
import enGB from './snippet/en-GB.json';
|
||||||
|
|
||||||
|
// Lazy (async) registration, as core does: the page chunk loads on first visit.
|
||||||
|
Shopware.Component.register('aeon-dump-manager-list', () => import('./page/aeon-dump-manager-list'));
|
||||||
|
|
||||||
Shopware.Module.register('aeon-dump-manager', {
|
Shopware.Module.register('aeon-dump-manager', {
|
||||||
type: 'plugin',
|
type: 'plugin',
|
||||||
name: 'DumpManager',
|
name: 'DumpManager',
|
||||||
@@ -27,12 +29,10 @@ Shopware.Module.register('aeon-dump-manager', {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Card on the Settings overview page's "System" group, next to Plugins/Cache.
|
settingsItem: [{
|
||||||
// Same mechanism every core settings module uses in 6.6 and 6.7 (no sidebar entry).
|
group: 'plugins',
|
||||||
settingsItem: {
|
|
||||||
group: 'system',
|
|
||||||
to: 'aeon.dump.manager.list',
|
to: 'aeon.dump.manager.list',
|
||||||
icon: 'regular-database',
|
icon: 'regular-database',
|
||||||
privilege: 'aeon_dump_manager.viewer',
|
privilege: 'aeon_dump_manager.viewer',
|
||||||
},
|
}],
|
||||||
});
|
});
|
||||||
+8
-8
@@ -1,7 +1,7 @@
|
|||||||
{% block aeon_dump_manager_list %}
|
{% block aeon_dump_manager_list %}
|
||||||
<sw-page class="aeon-dump-manager-list">
|
<sw-page class="aeon-dump-manager-list">
|
||||||
<template #smart-bar-actions>
|
<template #smart-bar-actions>
|
||||||
<sw-button
|
<mt-button
|
||||||
v-if="acl.can('aeon_dump_manager.creator')"
|
v-if="acl.can('aeon_dump_manager.creator')"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
:is-loading="pendingJob !== null"
|
:is-loading="pendingJob !== null"
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
@click="onCreate"
|
@click="onCreate"
|
||||||
>
|
>
|
||||||
{{ $tc('aeon-dump-manager.list.buttonCreate') }}
|
{{ $tc('aeon-dump-manager.list.buttonCreate') }}
|
||||||
</sw-button>
|
</mt-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
@@ -87,18 +87,18 @@
|
|||||||
>
|
>
|
||||||
<div class="aeon-dump-manager-list__progress-wrapper">
|
<div class="aeon-dump-manager-list__progress-wrapper">
|
||||||
<template v-if="pendingJob.status === 'done'">
|
<template v-if="pendingJob.status === 'done'">
|
||||||
<sw-alert variant="success">
|
<mt-banner variant="positive">
|
||||||
{{ $tc('aeon-dump-manager.list.createSuccess') }}
|
{{ $tc('aeon-dump-manager.list.createSuccess') }}
|
||||||
</sw-alert>
|
</mt-banner>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="pendingJob.status === 'failed'">
|
<template v-else-if="pendingJob.status === 'failed'">
|
||||||
<sw-alert variant="error">
|
<mt-banner variant="critical">
|
||||||
{{ $tc('aeon-dump-manager.list.createFailed', 0, { error: pendingJob.errorMessage || '' }) }}
|
{{ $tc('aeon-dump-manager.list.createFailed', 0, { error: pendingJob.errorMessage || '' }) }}
|
||||||
</sw-alert>
|
</mt-banner>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<sw-progress-bar
|
<mt-progress-bar
|
||||||
:value="pendingJob.percent || 0"
|
:model-value="pendingJob.percent || 0"
|
||||||
:max-value="100"
|
:max-value="100"
|
||||||
/>
|
/>
|
||||||
<span class="aeon-dump-manager-list__progress-text">
|
<span class="aeon-dump-manager-list__progress-text">
|
||||||
|
|||||||
+5
-4
@@ -1,7 +1,8 @@
|
|||||||
import template from './aeon-dump-manager-list.html.twig';
|
import template from './aeon-dump-manager-list.html.twig';
|
||||||
import type DumpApiService, { DumpFile, DumpJob } from '../../../../service/dump-api.service';
|
import type DumpApiService from '../../../../service/dump-api.service';
|
||||||
|
import type { DumpFile, DumpJob } from '../../../../service/dump-api.service';
|
||||||
|
|
||||||
const { Component, Mixin } = Shopware;
|
const { Mixin } = Shopware;
|
||||||
|
|
||||||
interface PendingJob {
|
interface PendingJob {
|
||||||
status: string;
|
status: string;
|
||||||
@@ -45,7 +46,7 @@ interface ComponentInstance extends ComponentData {
|
|||||||
listFilters: Record<string, unknown>[];
|
listFilters: Record<string, unknown>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.register('aeon-dump-manager-list', {
|
export default Shopware.Component.wrapComponentConfig({
|
||||||
template,
|
template,
|
||||||
|
|
||||||
mixins: [
|
mixins: [
|
||||||
@@ -147,7 +148,7 @@ Component.register('aeon-dump-manager-list', {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy(this: ComponentInstance) {
|
beforeUnmount(this: ComponentInstance) {
|
||||||
this.stopPolling();
|
this.stopPolling();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use AeonDumpManager\Service\Exception\DumpBinaryNotFoundException;
|
|||||||
use Doctrine\DBAL\Connection;
|
use Doctrine\DBAL\Connection;
|
||||||
use Shopware\Core\System\SystemConfig\SystemConfigService;
|
use Shopware\Core\System\SystemConfig\SystemConfigService;
|
||||||
use Symfony\Component\Process\ExecutableFinder;
|
use Symfony\Component\Process\ExecutableFinder;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Picks mariadb-dump/mysqldump depending on what the configured DB connection
|
* Picks mariadb-dump/mysqldump depending on what the configured DB connection
|
||||||
@@ -38,6 +39,19 @@ class DumpBinaryLocator
|
|||||||
throw DumpBinaryNotFoundException::create($binaryNames);
|
throw DumpBinaryNotFoundException::create($binaryNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string> client-specific flags for the located binary
|
||||||
|
*/
|
||||||
|
public function extraArguments(string $binary): array
|
||||||
|
{
|
||||||
|
$version = new Process([$binary, '--version']);
|
||||||
|
$version->run();
|
||||||
|
|
||||||
|
return MySqlVariant::needsColumnStatisticsOff($version->getOutput(), $this->isMariaDb())
|
||||||
|
? ['--column-statistics=0']
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
private function isMariaDb(): bool
|
private function isMariaDb(): bool
|
||||||
{
|
{
|
||||||
// Connection::getServerVersion() is private in the DBAL version this
|
// Connection::getServerVersion() is private in the DBAL version this
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class DumpService
|
|||||||
$binary,
|
$binary,
|
||||||
'--single-transaction',
|
'--single-transaction',
|
||||||
'--quick',
|
'--quick',
|
||||||
|
...$this->dumpBinaryLocator->extraArguments($binary),
|
||||||
'-h', (string) ($params['host'] ?? '127.0.0.1'),
|
'-h', (string) ($params['host'] ?? '127.0.0.1'),
|
||||||
'-P', (string) ($params['port'] ?? 3306),
|
'-P', (string) ($params['port'] ?? 3306),
|
||||||
'-u', (string) ($params['user'] ?? 'root'),
|
'-u', (string) ($params['user'] ?? 'root'),
|
||||||
|
|||||||
@@ -14,4 +14,18 @@ class MySqlVariant
|
|||||||
{
|
{
|
||||||
return stripos($serverVersion, 'mariadb') !== false;
|
return stripos($serverVersion, 'mariadb') !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL 8+ mysqldump queries information_schema.COLUMN_STATISTICS, which
|
||||||
|
* MariaDB lacks (error 1109); --column-statistics=0 skips it. MariaDB's own
|
||||||
|
* client (version string contains "MariaDB") and MySQL < 8 don't know the flag.
|
||||||
|
*/
|
||||||
|
public static function needsColumnStatisticsOff(string $clientVersion, bool $serverIsMariaDb): bool
|
||||||
|
{
|
||||||
|
return $serverIsMariaDb
|
||||||
|
&& !self::isMariaDb($clientVersion)
|
||||||
|
// MySQL < 8 prints "Ver 10.13 Distrib 5.7.x": the Distrib number is the real version.
|
||||||
|
&& (preg_match('/Distrib (\d+)\./', $clientVersion, $m) === 1 || preg_match('/\bVer (\d+)\./', $clientVersion, $m) === 1)
|
||||||
|
&& (int) $m[1] >= 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,4 +21,20 @@ class MySqlVariantTest extends TestCase
|
|||||||
yield 'mariadb without legacy prefix' => ['10.11.2-MariaDB', true];
|
yield 'mariadb without legacy prefix' => ['10.11.2-MariaDB', true];
|
||||||
yield 'mariadb lowercase' => ['10.11.2-mariadb', true];
|
yield 'mariadb lowercase' => ['10.11.2-mariadb', true];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[DataProvider('columnStatisticsProvider')]
|
||||||
|
public function testNeedsColumnStatisticsOff(string $clientVersion, bool $serverIsMariaDb, bool $expected): void
|
||||||
|
{
|
||||||
|
self::assertSame($expected, MySqlVariant::needsColumnStatisticsOff($clientVersion, $serverIsMariaDb));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function columnStatisticsProvider(): iterable
|
||||||
|
{
|
||||||
|
$mysql8 = 'mysqldump Ver 8.0.46-0ubuntu0.24.04.4 for Linux on x86_64 ((Ubuntu))';
|
||||||
|
yield 'mysql 8 client, mariadb server' => [$mysql8, true, true];
|
||||||
|
yield 'mysql 8 client, mysql server' => [$mysql8, false, false];
|
||||||
|
yield 'mysql 5.7 client, mariadb server' => ['mysqldump Ver 10.13 Distrib 5.7.44, for Linux (x86_64)', true, false];
|
||||||
|
yield 'mariadb client, mariadb server' => ['mariadb-dump from 11.4.2-MariaDB, client 10.19 for debian-linux-gnu (x86_64)', true, false];
|
||||||
|
yield 'mariadb legacy mysqldump name' => ['mysqldump Ver 10.19 Distrib 10.11.6-MariaDB, for debian-linux-gnu (x86_64)', true, false];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user