diff options
Diffstat (limited to 'library/Icinga/Web/Widget/ItemList/MigrationListItem.php')
-rw-r--r-- | library/Icinga/Web/Widget/ItemList/MigrationListItem.php | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/library/Icinga/Web/Widget/ItemList/MigrationListItem.php b/library/Icinga/Web/Widget/ItemList/MigrationListItem.php new file mode 100644 index 0000000..284ce4c --- /dev/null +++ b/library/Icinga/Web/Widget/ItemList/MigrationListItem.php @@ -0,0 +1,151 @@ +<?php + +/* Icinga Web 2 | (c) 2023 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Web\Widget\ItemList; + +use Icinga\Application\Hook\Common\DbMigrationStep; +use Icinga\Application\Hook\DbMigrationHook; +use ipl\Html\Attributes; +use ipl\Html\BaseHtmlElement; +use ipl\Html\Contract\FormElement; +use ipl\Html\FormattedString; +use ipl\Html\Html; +use ipl\Html\HtmlElement; +use ipl\Html\HtmlString; +use ipl\Html\Text; +use ipl\I18n\Translation; +use ipl\Web\Common\BaseListItem; +use ipl\Web\Url; +use ipl\Web\Widget\EmptyState; +use ipl\Web\Widget\Icon; +use ipl\Web\Widget\Link; +use LogicException; + +class MigrationListItem extends BaseListItem +{ + use Translation; + + /** @var ?FormElement */ + protected $migrateButton; + + /** @var DbMigrationHook Just for type hint */ + protected $item; + + /** + * Set a migration form of this list item + * + * @param FormElement $migrateButton + * + * @return $this + */ + public function setMigrateButton(FormElement $migrateButton): self + { + $this->migrateButton = $migrateButton; + + return $this; + } + + protected function assembleTitle(BaseHtmlElement $title): void + { + $title->addHtml( + FormattedString::create( + t('%s ', '<name>'), + HtmlElement::create('span', ['class' => 'subject'], $this->item->getName()) + ) + ); + } + + protected function assembleHeader(BaseHtmlElement $header): void + { + if ($this->migrateButton === null) { + throw new LogicException('Please set the migrate submit button beforehand'); + } + + $header->addHtml($this->createTitle()); + $header->addHtml($this->migrateButton); + } + + protected function assembleCaption(BaseHtmlElement $caption): void + { + $migrations = $this->item->getMigrations(); + /** @var DbMigrationStep $migration */ + $migration = array_shift($migrations); + if ($migration->getLastState()) { + if ($migration->getDescription()) { + $caption->addHtml(Text::create($migration->getDescription())); + } else { + $caption->addHtml(new EmptyState(Text::create($this->translate('No description provided.')))); + } + + $scriptPath = $migration->getScriptPath(); + /** @var string $parentDirs */ + $parentDirs = substr($scriptPath, (int) strpos($scriptPath, 'schema')); + $parentDirs = substr($parentDirs, 0, strrpos($parentDirs, '/') + 1); + + $title = new HtmlElement('div', Attributes::create(['class' => 'title'])); + $title->addHtml( + new HtmlElement('span', null, Text::create($parentDirs)), + new HtmlElement( + 'span', + Attributes::create(['class' => 'version']), + Text::create($migration->getVersion() . '.sql') + ), + new HtmlElement( + 'span', + Attributes::create(['class' => 'upgrade-failed']), + Text::create($this->translate('Upgrade failed')) + ) + ); + + $error = new HtmlElement('div', Attributes::create([ + 'class' => 'collapsible', + 'data-visible-height' => '58', + ])); + $error->addHtml(new HtmlElement('pre', null, new HtmlString(Html::escape($migration->getLastState())))); + + $errorSection = new HtmlElement('div', Attributes::create(['class' => 'errors-section',])); + $errorSection->addHtml( + new HtmlElement('header', null, new Icon('circle-xmark', ['class' => 'status-icon']), $title), + $caption, + $error + ); + + $caption->prependWrapper($errorSection); + } + } + + protected function assembleFooter(BaseHtmlElement $footer): void + { + $footer->addHtml((new MigrationList($this->item->getLatestMigrations(3)))->setMinimal(false)); + if ($this->item->count() > 3) { + $footer->addHtml( + new Link( + sprintf($this->translate('Show all %d migrations'), $this->item->count()), + Url::fromPath( + 'migrations/migration', + [DbMigrationHook::MIGRATION_PARAM => $this->item->getModuleName()] + ), + [ + 'data-base-target' => '_next', + 'class' => 'show-more' + ] + ) + ); + } + } + + protected function assembleMain(BaseHtmlElement $main): void + { + $main->addHtml($this->createHeader()); + $caption = $this->createCaption(); + if (! $caption->isEmpty()) { + $main->addHtml($caption); + } + + $footer = $this->createFooter(); + if ($footer) { + $main->addHtml($footer); + } + } +} |