From 6b2ad2097ccaa56a76ddae5b23182a320eb3531e Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Fri, 8 Nov 2024 15:00:17 +0100 Subject: [PATCH 1/9] Avoid accessing undefined array properties --- .../MigrationTool/Exporter/Item/Type/Page.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php index 4a81f00..f48eec6 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php @@ -23,13 +23,13 @@ public function exportCollection(ObjectCollection $collection, \SimpleXMLElement public function getResults(Request $request) { $pl = new PageList(); - $query = $request->query->all(); + $query = $request->query; - $keywords = $query['keywords']; - $ptID = $query['ptID']; - $startingPoint = intval($query['startingPoint']); - $datetime = \Core::make('helper/form/date_time')->translate('datetime', $query); - $includeSystemPages = $query['includeSystemPages']; + $keywords = $query->get('keywords'); + $ptID = $query->get('ptID'); + $startingPoint = (int) $query->get('startingPoint'); + $datetime = \Core::make('helper/form/date_time')->translate('datetime', $query->all()); + $includeSystemPages = $query->get('includeSystemPages'); $pl->ignorePermissions(); if ($startingPoint) { @@ -52,7 +52,7 @@ public function getResults(Request $request) if($includeSystemPages) { $pl->includeSystemPages(); } - + $pl->includeAliases(); $pl->setItemsPerPage(1000); $results = $pl->getResults(); $items = array(); From 582d4db8d2ffe1bd3f2feb434cdff83ba242eabe Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Fri, 8 Nov 2024 15:36:19 +0100 Subject: [PATCH 2/9] Add support for listing external links --- .../elements/export/search/page.php | 5 +- .../MigrationTool/Exporter/Item/Type/Page.php | 52 ++++++++++++++++++- .../Exporter/Item/Type/SinglePage.php | 8 ++- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/packages/migration_tool/elements/export/search/page.php b/packages/migration_tool/elements/export/search/page.php index 9a4fada..082a33d 100755 --- a/packages/migration_tool/elements/export/search/page.php +++ b/packages/migration_tool/elements/export/search/page.php @@ -34,6 +34,9 @@
- +
+
+ +
diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php index f48eec6..fcddfe3 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php @@ -1,6 +1,7 @@ getSiteTreeObject(); } else { $siteTree = \Core::make('site')->getActiveSiteForEditing()->getSiteTreeObject(); + $parent = null; } $pl->setSiteTreeObject($siteTree); if ($datetime) { @@ -51,8 +53,7 @@ public function getResults(Request $request) } if($includeSystemPages) { $pl->includeSystemPages(); - } - $pl->includeAliases(); + } $pl->setItemsPerPage(1000); $results = $pl->getResults(); $items = array(); @@ -66,6 +67,13 @@ public function getResults(Request $request) $item->setItemId($c->getCollectionID()); $items[] = $item; } + if ($query->get('includeExternalLinks')) { + foreach ($this->listExternalLinks($keywords, $parent) as $cID) { + $item = new \PortlandLabs\Concrete5\MigrationTool\Entity\Export\Page(); + $item->setItemId($cID); + $items[] = $item; + } + } return $items; } @@ -79,4 +87,44 @@ public function getPluralDisplayName() { return t('Pages'); } + + /** + * @param string $keywords + * @param \Concrete\Core\Page\Page|null $parent + * + * @return \Generator + */ + private function listExternalLinks($keywords, $parent = null) + { + $cn = \Core::make(Connection::class); + /* @var Connection $cn */ + $qb = $cn->createQueryBuilder(); + $qb + ->select('p.cID') + ->from('Pages', 'p') + ->andWhere("p.cPointerExternalLink IS NOT NULL AND p.cPointerExternalLink <> ''") + ; + $keywords = trim((string) $keywords); + if ($keywords !== '') { + $qb + ->innerJoin('p', 'CollectionVersions', 'cv', 'p.cID = cv.cID') + ->andWhere('cv.cvID = (SELECT MAX(cvID) FROM CollectionVersions WHERE cID = cv.cID)') + ->andWhere('cv.cvName LIKE :keywords') + ->setParameter('keywords', "%{$keywords}%") + ; + } + $pathPrefix = $parent === null ? '' : ($parent->getCollectionPath() . '/'); + $rs = $qb->execute(); + while (($cID = $rs->fetchColumn()) !== false) { + $cID = (int) $cID; + if ($pathPrefix !== '') { + $externalLink = \Page::getByID($cID, 'RECENT'); + $externalLinkPath = $externalLink->generatePagePath(); + if (strpos($externalLinkPath, $pathPrefix) !== 0) { + continue; + } + } + yield $cID; + } + } } diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php index e7165bb..5470fad 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php @@ -31,9 +31,13 @@ public function exportCollection(ObjectCollection $collection, \SimpleXMLElement public function getResultColumns(ExportItem $exportItem) { $c = \Page::getByID($exportItem->getItemIdentifier()); - + if ($c->isExternalLink()) { + $path = $c->generatePagePath(); + } else { + $path = $c->getCollectionPath() ?: '/'; + } return array( - $c->getCollectionPath() ?: '/', + $path, $c->getCollectionName(), ); } From d78fb75a742c8f02b0962183937c9400a7e084b9 Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Sat, 9 Nov 2024 10:58:55 +0100 Subject: [PATCH 3/9] Add support for listing page aliases --- packages/migration_tool/elements/export/search/page.php | 3 +++ .../Concrete5/MigrationTool/Exporter/Item/Type/Page.php | 9 +++++++-- .../MigrationTool/Exporter/Item/Type/SinglePage.php | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/migration_tool/elements/export/search/page.php b/packages/migration_tool/elements/export/search/page.php index 082a33d..fc2d12b 100755 --- a/packages/migration_tool/elements/export/search/page.php +++ b/packages/migration_tool/elements/export/search/page.php @@ -39,4 +39,7 @@
+
+ +
diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php index fcddfe3..c889e81 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Page.php @@ -31,6 +31,7 @@ public function getResults(Request $request) $startingPoint = (int) $query->get('startingPoint'); $datetime = \Core::make('helper/form/date_time')->translate('datetime', $query->all()); $includeSystemPages = $query->get('includeSystemPages'); + $includeAliases = $query->get('includeAliases'); $pl->ignorePermissions(); if ($startingPoint) { @@ -51,9 +52,12 @@ public function getResults(Request $request) if ($keywords) { $pl->filterByKeywords($keywords); } - if($includeSystemPages) { + if ($includeSystemPages) { $pl->includeSystemPages(); } + if ($includeAliases) { + $pl->includeAliases(); + } $pl->setItemsPerPage(1000); $results = $pl->getResults(); $items = array(); @@ -64,7 +68,8 @@ public function getResults(Request $request) } foreach ($results as $c) { $item = new \PortlandLabs\Concrete5\MigrationTool\Entity\Export\Page(); - $item->setItemId($c->getCollectionID()); + $cID = $includeAliases ? $c->getCollectionPointerOriginalID() : 0; + $item->setItemId($cID ?: $c->getCollectionID()); $items[] = $item; } if ($query->get('includeExternalLinks')) { diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php index 5470fad..97ab4a4 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php @@ -49,7 +49,7 @@ public function getItemsFromRequest($array) $c = \Page::getByID($id); if (is_object($c) && !$c->isError()) { $page = new \PortlandLabs\Concrete5\MigrationTool\Entity\Export\SinglePage(); - $page->setItemId($c->getCollectionID()); + $page->setItemId($c->getCollectionPointerOriginalID() ?: $c->getCollectionID()); $items[] = $page; } } From 559eb8449107d857779f223d5622c86ae2e52a16 Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Sat, 9 Nov 2024 11:11:45 +0100 Subject: [PATCH 4/9] Display details about aliases and external links --- .../MigrationTool/Exporter/Item/Type/SinglePage.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php index 97ab4a4..f099a68 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/SinglePage.php @@ -32,13 +32,18 @@ public function getResultColumns(ExportItem $exportItem) { $c = \Page::getByID($exportItem->getItemIdentifier()); if ($c->isExternalLink()) { - $path = $c->generatePagePath(); + $path = h($c->generatePagePath()); + $path .= ' ' . h($c->getCollectionPointerExternalLink()); } else { - $path = $c->getCollectionPath() ?: '/'; + $path = h($c->getCollectionPath() ?: '/'); + if ($c->isAliasPage()) { + $originalPage = \Page::getByID($c->getCollectionID()); + $path .= ' ' . h($originalPage->getCollectionPath()); + } } return array( $path, - $c->getCollectionName(), + h($c->getCollectionName()), ); } From ca616c75e3f3c0387729b5311812048702f343d3 Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Wed, 20 Nov 2024 15:53:57 +0100 Subject: [PATCH 5/9] Remove unused "use" statement --- .../single_page/dashboard/system/migration/export.php | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php b/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php index 7fce89c..820af4d 100644 --- a/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php +++ b/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php @@ -4,7 +4,6 @@ use Concrete\Core\Application\EditResponse; use Concrete\Core\File\File; use Concrete\Core\Page\Controller\DashboardSitePageController; -use Concrete\Package\MigrationTool\Page\Controller\DashboardPageController; use Doctrine\Common\Collections\ArrayCollection; use PortlandLabs\Concrete5\MigrationTool\Entity\Export\Batch; use PortlandLabs\Concrete5\MigrationTool\Entity\Export\ObjectCollection; From 4eb469952c83f868e8321d4df8b5e66effaa3e2b Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Wed, 20 Nov 2024 15:54:23 +0100 Subject: [PATCH 6/9] Disable exporting aliases/external links if unsupported --- .../elements/export/search/page.php | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/migration_tool/elements/export/search/page.php b/packages/migration_tool/elements/export/search/page.php index fc2d12b..03d8ea2 100755 --- a/packages/migration_tool/elements/export/search/page.php +++ b/packages/migration_tool/elements/export/search/page.php @@ -10,6 +10,11 @@ foreach ($list as $type) { $pagetypes[$type->getPageTypeID()] = $type->getPageTypeDisplayName(); } +if (version_compare(APP_VERSION, '8.5.19') <= 0) { + $whyNoAdditionalTypes = t("Your version of concrete5 doesn't support exporting external links and aliases: please upgrade to a newer version."); +} else { + $whyNoAdditionalTypes = ''; +} ?>
@@ -34,12 +39,35 @@
- +
- +
- +
From 542faae15996f6503a971e74b3cb7a61f69dce0f Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Thu, 16 Jan 2025 14:44:04 +0100 Subject: [PATCH 7/9] Improve check of exportability of aliases/external links --- packages/migration_tool/elements/export/search/page.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/migration_tool/elements/export/search/page.php b/packages/migration_tool/elements/export/search/page.php index 03d8ea2..b49c69c 100755 --- a/packages/migration_tool/elements/export/search/page.php +++ b/packages/migration_tool/elements/export/search/page.php @@ -10,10 +10,11 @@ foreach ($list as $type) { $pagetypes[$type->getPageTypeID()] = $type->getPageTypeDisplayName(); } -if (version_compare(APP_VERSION, '8.5.19') <= 0) { - $whyNoAdditionalTypes = t("Your version of concrete5 doesn't support exporting external links and aliases: please upgrade to a newer version."); -} else { +// Let's check if we have a class that has been introduced in the core when we added support for exporting page aliases and external links +if (class_exists('Concrete\Core\Backup\ContentImporter\Exception\MissingPageAtPathException')) { $whyNoAdditionalTypes = ''; +} else { + $whyNoAdditionalTypes = t("Your version of concrete5 doesn't support exporting external links and aliases: please upgrade to a newer version."); } ?>
From 6359b563ea6ea07f9fb081fd9920d58e8151b60c Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Mon, 3 Feb 2025 14:02:32 +0100 Subject: [PATCH 8/9] Display "Global Area" type --- .../Concrete5/MigrationTool/Exporter/Item/Type/Stack.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Stack.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Stack.php index 778b728..7354bf7 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Stack.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Item/Type/Stack.php @@ -51,7 +51,11 @@ public function getResultColumns(ExportItem $exportItem) break; default: $c = \Concrete\Core\Page\Stack\Stack::getByID($exportItem->getItemIdentifier()); - $type = t('Stack'); + if ($c && !$c->isError() && $c->getStackType() == $c::ST_TYPE_GLOBAL_AREA) { + $type = t('Global Area'); + } else { + $type = t('Stack'); + } break; } From b03d19efad4f25ab11c08381691e322082b561f7 Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Wed, 5 Feb 2025 11:18:17 +0100 Subject: [PATCH 9/9] Build the export SimpleXMLElement only once --- .../dashboard/system/migration/export.php | 55 ++++---- .../migration/finalize_export_batch.php | 121 ++++++++++++------ .../MigrationTool/Exporter/Exporter.php | 15 ++- 3 files changed, 122 insertions(+), 69 deletions(-) diff --git a/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php b/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php index 820af4d..1e48ba4 100644 --- a/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php +++ b/packages/migration_tool/controllers/single_page/dashboard/system/migration/export.php @@ -80,16 +80,34 @@ public function export_batch($id = null) { $r = $this->entityManager->getRepository('\PortlandLabs\Concrete5\MigrationTool\Entity\Export\Batch'); $batch = $r->findOneById($id); - if (is_object($batch)) { - $exporter = new Exporter($batch); - $files = $exporter->getReferencedFiles(); - $this->set('files', $files); - $this->set('batch', $batch); - $this->set('pageTitle', t('Export Batch')); - $this->render('/dashboard/system/migration/finalize_export_batch'); - } else { - $this->view(); + if ($batch === null) { + return $this->view(); } + $this->set('batch', $batch); + $exporter = new Exporter($batch); + $files = $exporter->getReferencedFiles(); + $this->set('files', $files); + $sx = $exporter->getElement(); + $xml = $sx->saveXML(); + try { + $doc = new \DOMDocument(); + $doc->preserveWhiteSpace = false; + $doc->formatOutput = true; + $flags = 0 | (defined('LIBXML_BIGLINES') ? LIBXML_BIGLINES : 0); + $restore = libxml_use_internal_errors(true); + try { + if ($doc->loadXML($xml, $flags) !== false && !libxml_get_errors()) { + $xml = $doc->saveXML(); + } + } finally { + libxml_use_internal_errors($restore); + } + } catch (\Exception $_) { + } catch (\Throwable $_) { + } + $this->set('xml', $xml); + $this->set('pageTitle', t('Export Batch')); + $this->render('/dashboard/system/migration/finalize_export_batch'); } public function download_files() @@ -151,25 +169,6 @@ public function download_files() exit; } - public function export_batch_xml($id = null) - { - $r = $this->entityManager->getRepository('\PortlandLabs\Concrete5\MigrationTool\Entity\Export\Batch'); - $batch = $r->findOneById($id); - if (is_object($batch)) { - $exporter = new Exporter($batch); - if ($this->request->request->get('download')) { - header('Content-disposition: attachment; filename="export.xml"'); - header('Content-type: "text/xml"; charset="utf8"'); - } else { - header('Content-type: text/xml'); - } - echo $exporter->getElement()->asXML(); - exit; - } else { - $this->view(); - } - } - public function add_items_to_batch() { if (!$this->token->validate('add_items_to_batch')) { diff --git a/packages/migration_tool/single_pages/dashboard/system/migration/finalize_export_batch.php b/packages/migration_tool/single_pages/dashboard/system/migration/finalize_export_batch.php index ad892dc..d058173 100755 --- a/packages/migration_tool/single_pages/dashboard/system/migration/finalize_export_batch.php +++ b/packages/migration_tool/single_pages/dashboard/system/migration/finalize_export_batch.php @@ -1,12 +1,25 @@ - +
- +
- - - - -
- - output('download_files')?> - -

- + + output('download_files') ?> + + +

- - - - - - - - - - - + + + - + + + + + + + + +
getFileID()?>getFileName()?>
getFileID() ?>getFileName()) ?>
- -

-

- +

+

+ +

+
+ + +
+ diff --git a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Exporter.php b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Exporter.php index 1d9453e..77c94b1 100644 --- a/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Exporter.php +++ b/packages/migration_tool/src/PortlandLabs/Concrete5/MigrationTool/Exporter/Exporter.php @@ -8,8 +8,14 @@ class Exporter { + /** + * @var \PortlandLabs\Concrete5\MigrationTool\Entity\Export\Batch + */ protected $batch; - protected $built = false; + + /** + * @var \SimpleXMLElement|null + */ protected $element; public function __construct(Batch $batch) @@ -27,9 +33,12 @@ protected function build() } } + /** + * @return \SimpleXMLElement + */ public function getElement() { - if (!$this->built) { + if (!$this->element) { $this->build(); } @@ -38,6 +47,8 @@ public function getElement() /** * Loops through all pages and returns files referenced. + * + * @return \Concrete\Core\Entity\File\File[] */ public function getReferencedFiles() {