mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0b50824e46 | ||
|
b1efcc217d | ||
|
f2d745afec | ||
|
f705df4b0c | ||
|
7fe9a04112 | ||
|
3f1dbe4d3f | ||
|
abf00ede95 | ||
|
93f57d2300 | ||
|
222972c687 | ||
|
b02beba7ba | ||
|
081eea42c5 | ||
|
30685c9227 | ||
|
37af732dbf | ||
|
18cb6d499d | ||
|
2b0374e692 | ||
|
f362d8b129 | ||
|
9bb6f700b4 | ||
|
69fabe9a34 | ||
|
b57d557bc7 | ||
|
97fdff4bb2 | ||
|
50cefa6d14 | ||
|
1bd578fc96 | ||
|
61d729285f | ||
|
a44547915d | ||
|
e7d9d1b36e | ||
|
3c7459208e | ||
|
ef4122da04 | ||
|
b9115f3f6d | ||
|
dd79cf5a23 | ||
|
cba1acb88e | ||
|
bd42008584 | ||
|
5e843d2619 | ||
|
ddbe4ea4ce | ||
|
145f063c33 | ||
|
03bac4b72d | ||
|
605daf5026 | ||
|
0e5428b78b | ||
|
8b1433b263 | ||
|
3186e0e129 | ||
|
911a71d6f6 | ||
|
003f9ba750 | ||
|
2d10a624b3 | ||
|
af1a482d20 | ||
|
8320023526 | ||
|
6e19ae737f | ||
|
9b64c7de24 | ||
|
ea9ce63438 | ||
|
6ff98c4201 | ||
|
e5cea70b54 | ||
|
d7857ebbe0 | ||
|
390f078551 | ||
|
bedd64554f | ||
|
7368df8757 | ||
|
d56682509c | ||
|
aa4ba82f38 | ||
|
f2c4423d0c | ||
|
1711c0c88e | ||
|
adcea213a2 | ||
|
f9a19e7429 | ||
|
803b4add7b | ||
|
cda7857e12 | ||
|
b46876b8a8 | ||
|
c130b55ecb | ||
|
2219899c10 | ||
|
859ff00184 | ||
|
7381de15e8 | ||
|
e580527111 | ||
|
72f8e5f71d |
161
.upgrade.yml
161
.upgrade.yml
@ -1,161 +0,0 @@
|
|||||||
mappings:
|
|
||||||
CMSBatchAction_Publish: SilverStripe\CMS\BatchActions\CMSBatchAction_Publish
|
|
||||||
CMSBatchAction_Unpublish: SilverStripe\CMS\BatchActions\CMSBatchAction_Unpublish
|
|
||||||
CMSBatchAction_Archive: SilverStripe\CMS\BatchActions\CMSBatchAction_Archive
|
|
||||||
CMSBatchAction_Restore: SilverStripe\CMS\BatchActions\CMSBatchAction_Restore
|
|
||||||
CMSMain: SilverStripe\CMS\Controllers\CMSMain
|
|
||||||
CMSPageAddController: SilverStripe\CMS\Controllers\CMSPageAddController
|
|
||||||
CMSPageEditController: SilverStripe\CMS\Controllers\CMSPageEditController
|
|
||||||
CMSPageHistoryController: SilverStripe\CMS\Controllers\CMSPageHistoryController
|
|
||||||
CMSPagesController: SilverStripe\CMS\Controllers\CMSPagesController
|
|
||||||
CMSPageSettingsController: SilverStripe\CMS\Controllers\CMSPageSettingsController
|
|
||||||
CMSSiteTreeFilter: SilverStripe\CMS\Controllers\CMSSiteTreeFilter
|
|
||||||
CMSSiteTreeFilter_PublishedPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_PublishedPages
|
|
||||||
CMSSiteTreeFilter_DeletedPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_DeletedPages
|
|
||||||
CMSSiteTreeFilter_ChangedPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_ChangedPages
|
|
||||||
CMSSiteTreeFilter_StatusRemovedFromDraftPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_StatusRemovedFromDraftPages
|
|
||||||
CMSSiteTreeFilter_StatusDraftPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_StatusDraftPages
|
|
||||||
CMSSiteTreeFilter_StatusDeletedPages: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_StatusDeletedPages
|
|
||||||
CMSSiteTreeFilter_Search: SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search
|
|
||||||
ContentController: SilverStripe\CMS\Controllers\ContentController
|
|
||||||
ErrorPageControllerExtension: SilverStripe\ErrorPage\ErrorPageControllerExtension
|
|
||||||
ErrorPageFileExtension: SilverStripe\ErrorPage\ErrorPageFileExtension
|
|
||||||
LeftAndMainPageIconsExtension: SilverStripe\CMS\Controllers\LeftAndMainPageIconsExtension
|
|
||||||
ModelAsController: SilverStripe\CMS\Controllers\ModelAsController
|
|
||||||
OldPageRedirector: SilverStripe\CMS\Controllers\OldPageRedirector
|
|
||||||
RootURLController: SilverStripe\CMS\Controllers\RootURLController
|
|
||||||
SilverStripeNavigator: SilverStripe\CMS\Controllers\SilverStripeNavigator
|
|
||||||
SilverStripeNavigatorItem: SilverStripe\CMS\Controllers\SilverStripeNavigatorItem
|
|
||||||
SilverStripeNavigatorItem_CMSLink: SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_CMSLink
|
|
||||||
SilverStripeNavigatorItem_StageLink: SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_StageLink
|
|
||||||
SilverStripeNavigatorItem_LiveLink: SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_LiveLink
|
|
||||||
SilverStripeNavigatorItem_ArchiveLink: SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_ArchiveLink
|
|
||||||
SiteTreeURLSegmentField: SilverStripe\CMS\Forms\SiteTreeURLSegmentField
|
|
||||||
SiteTreeURLSegmentField_Readonly: SilverStripe\CMS\Forms\SiteTreeURLSegmentField_Readonly
|
|
||||||
CurrentPageIdentifier: SilverStripe\CMS\Model\CurrentPageIdentifier
|
|
||||||
ErrorPage: SilverStripe\ErrorPage\ErrorPage
|
|
||||||
ErrorPage_Controller: SilverStripe\ErrorPage\ErrorPageController
|
|
||||||
RedirectorPage: SilverStripe\CMS\Model\RedirectorPage
|
|
||||||
RedirectorPage_Controller: SilverStripe\CMS\Model\RedirectorPageController
|
|
||||||
SiteTree: SilverStripe\CMS\Model\SiteTree
|
|
||||||
SiteTreeExtension: SilverStripe\CMS\Model\SiteTreeExtension
|
|
||||||
SiteTreeFileExtension: SilverStripe\CMS\Model\SiteTreeFileExtension
|
|
||||||
SiteTreeFolderExtension: SilverStripe\CMS\Model\SiteTreeFolderExtension
|
|
||||||
SiteTreeLinkTracking: SilverStripe\CMS\Model\SiteTreeLinkTracking
|
|
||||||
SiteTreeLinkTracking_Parser: SilverStripe\CMS\Model\SiteTreeLinkTracking_Parser
|
|
||||||
VirtualPage: SilverStripe\CMS\Model\VirtualPage
|
|
||||||
BrokenFilesReport: SilverStripe\CMS\Reports\BrokenFilesReport
|
|
||||||
SideReport_BrokenFiles: SilverStripe\CMS\Reports\BrokenFilesReport
|
|
||||||
BrokenLinksReport: SilverStripe\CMS\Reports\BrokenLinksReport
|
|
||||||
SideReport_BrokenLinks: SilverStripe\CMS\Reports\BrokenLinksReport
|
|
||||||
BrokenRedirectorPagesReport: SilverStripe\CMS\Reports\BrokenRedirectorPagesReport
|
|
||||||
SideReport_BrokenRedirectorPages: SilverStripe\CMS\Reports\BrokenRedirectorPagesReport
|
|
||||||
BrokenVirtualPagesReport: SilverStripe\CMS\Reports\BrokenVirtualPagesReport
|
|
||||||
SideReport_BrokenVirtualPages: SilverStripe\CMS\Reports\BrokenVirtualPagesReport
|
|
||||||
EmptyPagesReport: SilverStripe\CMS\Reports\EmptyPagesReport
|
|
||||||
SideReport_EmptyPages: SilverStripe\CMS\Reports\EmptyPagesReport
|
|
||||||
RecentlyEditedReport: SilverStripe\CMS\Reports\RecentlyEditedReport
|
|
||||||
SideReport_RecentlyEdited: SilverStripe\CMS\Reports\RecentlyEditedReport
|
|
||||||
ContentControllerSearchExtension: SilverStripe\CMS\Search\ContentControllerSearchExtension
|
|
||||||
SearchForm: SilverStripe\CMS\Search\SearchForm
|
|
||||||
MigrateSiteTreeLinkingTask: SilverStripe\CMS\Tasks\MigrateSiteTreeLinkingTask
|
|
||||||
RemoveOrphanedPagesTask: SilverStripe\CMS\Tasks\RemoveOrphanedPagesTask
|
|
||||||
SiteTreeMaintenanceTask: SilverStripe\CMS\Tasks\SiteTreeMaintenanceTask
|
|
||||||
AssetAdmin: SilverStripe\AssetAdmin\Controller\AssetAdmin
|
|
||||||
AssetTableField: SilverStripe\AssetAdmin\Controller\AssetAdmin
|
|
||||||
CMSAddPageController: SilverStripe\CMS\Controllers\CMSPageAddController
|
|
||||||
CMSBatchActions: SilverStripe\Admin\CMSBatchAction
|
|
||||||
CMSSearch: SilverStripe\CMS\Search\SearchForm
|
|
||||||
ContentControl: SilverStripe\CMS\Controllers\ContentController
|
|
||||||
Permissions: SilverStripe\Security\Permission
|
|
||||||
SITETREE: SilverStripe\CMS\Model\SiteTree
|
|
||||||
CMSMain_left_ss: SilverStripe\CMS\Controllers\CMSMain
|
|
||||||
CMSPageHistoryController_versions_ss: SilverStripe\CMS\Controllers\CMSPageHistoryController
|
|
||||||
CMSPagesController_ContentToolbar_ss: SilverStripe\CMS\Controllers\CMSPageHistoryController
|
|
||||||
CMSSIteTreeFilter_PublishedPages: SilverStripe\CMS\Controllers\CMSSIteTreeFilter_PublishedPages
|
|
||||||
URLSegmentField: SilverStripe\CMS\Forms\SiteTreeURLSegmentField
|
|
||||||
CMSPagesController_Tools_ss: SilverStripe\CMS\Controllers\CMSPagesController
|
|
||||||
LeftAndMain: SilverStripe\Admin\LeftAndMain
|
|
||||||
CMSBatchActionsTest: SilverStripe\CMS\Tests\CMSBatchActionsTest
|
|
||||||
CMSMainTest: SilverStripe\CMS\Tests\CMSMainTest
|
|
||||||
CMSMainTest_ClassA: SilverStripe\CMS\Tests\CMSMainTest_ClassA
|
|
||||||
CMSMainTest_ClassB: SilverStripe\CMS\Tests\CMSMainTest_ClassB
|
|
||||||
CMSMainTest_HiddenClass: SilverStripe\CMS\Tests\CMSMainTest_HiddenClass
|
|
||||||
CMSMainTest_NotRoot: SilverStripe\CMS\Tests\CMSMainTest_NotRoot
|
|
||||||
CMSPageHistoryControllerTest: SilverStripe\CMS\Tests\CMSPageHistoryControllerTest
|
|
||||||
CMSSiteTreeFilterTest: SilverStripe\CMS\Tests\CMSSiteTreeFilterTest
|
|
||||||
CMSTreeTest: SilverStripe\CMS\Tests\CMSTreeTest
|
|
||||||
ContentControllerPermissionsTest: SilverStripe\CMS\Tests\ContentControllerPermissionsTest
|
|
||||||
ContentControllerSearchExtensionTest: SilverStripe\CMS\Tests\ContentControllerSearchExtensionTest
|
|
||||||
ContentControllerTest: SilverStripe\CMS\Tests\ContentControllerTest
|
|
||||||
ContentControllerTest_Page: SilverStripe\CMS\Tests\ContentControllerTest_Page
|
|
||||||
ContentControllerTest_PageController: SilverStripe\CMS\Tests\ContentControllerTest_PageController
|
|
||||||
ContentControllerTestPage: SilverStripe\CMS\Tests\ContentControllerTestPage
|
|
||||||
ContentControllerTestPageController: SilverStripe\CMS\Tests\ContentControllerTestPageController
|
|
||||||
ContentControllerTestPageWithoutController: SilverStripe\CMS\Tests\ContentControllerTestPageWithoutController
|
|
||||||
ModelAsControllerTest: SilverStripe\CMS\Tests\ModelAsControllerTest
|
|
||||||
RootURLControllerTest: SilverStripe\CMS\Tests\RootURLControllerTest
|
|
||||||
SilverStripeNavigatorTest: SilverStripe\CMS\Tests\SilverStripeNavigatorTest
|
|
||||||
SilverStripeNavigatorTest_ProtectedTestItem: SilverStripe\CMS\Tests\SilverStripeNavigatorTest_ProtectedTestItem
|
|
||||||
SilverStripeNavigatorTest_TestItem: SilverStripe\CMS\Tests\SilverStripeNavigatorTest_TestItem
|
|
||||||
FileLinkTrackingTest: SilverStripe\CMS\Tests\FileLinkTrackingTest
|
|
||||||
RedirectorPageTest: SilverStripe\CMS\Tests\RedirectorPageTest
|
|
||||||
RedirectorPageTest_RedirectExtension: SilverStripe\CMS\Tests\RedirectorPageTest_RedirectExtension
|
|
||||||
SiteTreeActionsTest: SilverStripe\CMS\Tests\SiteTreeActionsTest
|
|
||||||
SiteTreeActionsTest_Page: SilverStripe\CMS\Tests\SiteTreeActionsTest_Page
|
|
||||||
SiteTreeBacklinksTest: SilverStripe\CMS\Tests\SiteTreeBacklinksTest
|
|
||||||
SiteTreeBacklinksTest_DOD: SilverStripe\CMS\Tests\SiteTreeBacklinksTest_DOD
|
|
||||||
SiteTreeBrokenLinksTest: SilverStripe\CMS\Tests\SiteTreeBrokenLinksTest
|
|
||||||
SiteTreeHTMLEditorFieldTest: SilverStripe\CMS\Tests\SiteTreeHTMLEditorFieldTest
|
|
||||||
SiteTreeLinkTrackingTest: SilverStripe\CMS\Tests\SiteTreeLinkTrackingTest
|
|
||||||
SiteTreePermissionsTest: SilverStripe\CMS\Tests\SiteTreePermissionsTest
|
|
||||||
SiteTreeTest: SilverStripe\CMS\Tests\SiteTreeTest
|
|
||||||
SiteTreeTest_AdminDenied: SilverStripe\CMS\Tests\SiteTreeTest_AdminDenied
|
|
||||||
SiteTreeTest_AdminDeniedExtension: SilverStripe\CMS\Tests\SiteTreeTest_AdminDeniedExtension
|
|
||||||
SiteTreeTest_ClassA: SilverStripe\CMS\Tests\SiteTreeTest_ClassA
|
|
||||||
SiteTreeTest_ClassB: SilverStripe\CMS\Tests\SiteTreeTest_ClassB
|
|
||||||
SiteTreeTest_ClassC: SilverStripe\CMS\Tests\SiteTreeTest_ClassC
|
|
||||||
SiteTreeTest_ClassCext: SilverStripe\CMS\Tests\SiteTreeTest_ClassCext
|
|
||||||
SiteTreeTest_ClassD: SilverStripe\CMS\Tests\SiteTreeTest_ClassD
|
|
||||||
SiteTreeTest_ClassE: SilverStripe\CMS\Tests\SiteTreeTest_ClassE
|
|
||||||
SiteTreeTest_Conflicted: SilverStripe\CMS\Tests\SiteTreeTest_Conflicted
|
|
||||||
SiteTreeTest_ConflictedController: SilverStripe\CMS\Tests\SiteTreeTest_ConflictedController
|
|
||||||
SiteTreeTest_DataObject: SilverStripe\CMS\Tests\SiteTreeTest_DataObject
|
|
||||||
SiteTreeTest_Extension: SilverStripe\CMS\Tests\SiteTreeTest_Extension
|
|
||||||
SiteTreeTest_ExtensionA: SilverStripe\CMS\Tests\SiteTreeTest_ExtensionA
|
|
||||||
SiteTreeTest_ExtensionB: SilverStripe\CMS\Tests\SiteTreeTest_ExtensionB
|
|
||||||
SiteTreeTest_LegacyControllerName: SilverStripe\CMS\Tests\SiteTreeTest_LegacyControllerName
|
|
||||||
SiteTreeTest_LegacyControllerName_Controller: SilverStripe\CMS\Tests\SiteTreeTest_LegacyControllerName_Controller
|
|
||||||
SiteTreeTest_NotRoot: SilverStripe\CMS\Tests\SiteTreeTest_NotRoot
|
|
||||||
SiteTreeTest_NullHtmlCleaner: SilverStripe\CMS\Tests\SiteTreeTest_NullHtmlCleaner
|
|
||||||
SiteTreeTest_PageNode: SilverStripe\CMS\Tests\SiteTreeTest_PageNode
|
|
||||||
SiteTreeTest_PageNodeController: SilverStripe\CMS\Tests\SiteTreeTest_PageNodeController
|
|
||||||
SiteTreeTest_StageStatusInherit: SilverStripe\CMS\Tests\SiteTreeTest_StageStatusInherit
|
|
||||||
VirtualPageTest: SilverStripe\CMS\Tests\VirtualPageTest
|
|
||||||
VirtualPageTest_ClassA: SilverStripe\CMS\Tests\VirtualPageTest_ClassA
|
|
||||||
VirtualPageTest_ClassAController: SilverStripe\CMS\Tests\VirtualPageTest_ClassAController
|
|
||||||
VirtualPageTest_ClassB: SilverStripe\CMS\Tests\VirtualPageTest_ClassB
|
|
||||||
VirtualPageTest_ClassC: SilverStripe\CMS\Tests\VirtualPageTest_ClassC
|
|
||||||
VirtualPageTest_NotRoot: SilverStripe\CMS\Tests\VirtualPageTest_NotRoot
|
|
||||||
VirtualPageTest_PageExtension: SilverStripe\CMS\Tests\VirtualPageTest_PageExtension
|
|
||||||
VirtualPageTest_PageWithAllowedChildren: SilverStripe\CMS\Tests\VirtualPageTest_PageWithAllowedChildren
|
|
||||||
VirtualPageTest_TestDBField: SilverStripe\CMS\Tests\VirtualPageTest_TestDBField
|
|
||||||
VirtualPageTest_VirtualPageSub: SilverStripe\CMS\Tests\VirtualPageTest_VirtualPageSub
|
|
||||||
CmsReportsTest: SilverStripe\CMS\Tests\CmsReportsTest
|
|
||||||
CMSMainSearchFormTest: SilverStripe\CMS\Tests\CMSMainSearchFormTest
|
|
||||||
ZZZSearchFormTest: SilverStripe\CMS\Tests\ZZZSearchFormTest
|
|
||||||
MigrateSiteTreeLinkingTaskTest: SilverStripe\CMS\Tests\MigrateSiteTreeLinkingTaskTest
|
|
||||||
RemoveOrphanedPagesTaskTest: SilverStripe\CMS\Tests\RemoveOrphanedPagesTaskTest
|
|
||||||
excludedPaths:
|
|
||||||
- '*/_config/legacy.yml'
|
|
||||||
warnings:
|
|
||||||
methods:
|
|
||||||
'SilverStripe\CMS\Model\SiteTree->getIsAddedToStage()':
|
|
||||||
message: 'Moved to Versioned->isOnDraftOnly()'
|
|
||||||
replacement: 'isOnDraftOnly'
|
|
||||||
'SilverStripe\CMS\Model\SiteTree->getIsModifiedOnStage()':
|
|
||||||
message: 'Moved to Versioned->isModifiedOnDraft()'
|
|
||||||
replacement: 'isModifiedOnDraft'
|
|
||||||
'SilverStripe\CMS\Model\SiteTree->getExistsOnLive()':
|
|
||||||
message: 'Removed in favour of isPublished()'
|
|
||||||
replacement: 'isPublished'
|
|
@ -4,7 +4,6 @@ use SilverStripe\Admin\CMSMenu;
|
|||||||
use SilverStripe\CMS\Controllers\CMSMain;
|
use SilverStripe\CMS\Controllers\CMSMain;
|
||||||
use SilverStripe\CMS\Controllers\CMSPageAddController;
|
use SilverStripe\CMS\Controllers\CMSPageAddController;
|
||||||
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
||||||
use SilverStripe\CMS\Controllers\CMSPageHistoryController;
|
|
||||||
use SilverStripe\CMS\Controllers\CMSPageSettingsController;
|
use SilverStripe\CMS\Controllers\CMSPageSettingsController;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Core\Manifest\ModuleLoader;
|
use SilverStripe\Core\Manifest\ModuleLoader;
|
||||||
@ -37,8 +36,4 @@ ShortcodeParser::get('default')->register(
|
|||||||
CMSMenu::remove_menu_class(CMSMain::class);
|
CMSMenu::remove_menu_class(CMSMain::class);
|
||||||
CMSMenu::remove_menu_class(CMSPageEditController::class);
|
CMSMenu::remove_menu_class(CMSPageEditController::class);
|
||||||
CMSMenu::remove_menu_class(CMSPageSettingsController::class);
|
CMSMenu::remove_menu_class(CMSPageSettingsController::class);
|
||||||
if (class_exists(CMSPageHistoryController::class)) {
|
|
||||||
// this class will be removed in CMS 5
|
|
||||||
CMSMenu::remove_menu_class(CMSPageHistoryController::class);
|
|
||||||
}
|
|
||||||
CMSMenu::remove_menu_class(CMSPageAddController::class);
|
CMSMenu::remove_menu_class(CMSPageAddController::class);
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
Name: cmslegacy
|
|
||||||
---
|
|
||||||
SilverStripe\ORM\DatabaseAdmin:
|
|
||||||
classname_value_remapping:
|
|
||||||
SiteTree: 'SilverStripe\CMS\Model\SiteTree'
|
|
||||||
RedirectorPage: SilverStripe\CMS\Model\RedirectorPage
|
|
||||||
VirtualPage: SilverStripe\CMS\Model\VirtualPage
|
|
@ -5,8 +5,6 @@ After: '#coreroutes'
|
|||||||
SilverStripe\Control\Director:
|
SilverStripe\Control\Director:
|
||||||
rules:
|
rules:
|
||||||
'': 'SilverStripe\CMS\Controllers\RootURLController'
|
'': 'SilverStripe\CMS\Controllers\RootURLController'
|
||||||
'RemoveOrphanedPagesTask//$Action/$ID/$OtherID': 'SilverStripe\CMS\Tasks\RemoveOrphanedPagesTask'
|
|
||||||
'SiteTreeMaintenanceTask//$Action/$ID/$OtherID': 'SilverStripe\CMS\Tasks\SiteTreeMaintenanceTask'
|
|
||||||
---
|
---
|
||||||
Name: legacycmsroutes
|
Name: legacycmsroutes
|
||||||
---
|
---
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
Name: cmsversion
|
Name: cmsversion
|
||||||
After: 'framework/*'
|
After: 'framework/coreconfig'
|
||||||
---
|
---
|
||||||
SilverStripe\Core\Manifest\VersionProvider:
|
SilverStripe\Core\Manifest\VersionProvider:
|
||||||
modules:
|
modules:
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\GraphQL;
|
|
||||||
|
|
||||||
use GraphQL\Type\Definition\ResolveInfo;
|
|
||||||
use SilverStripe\Core\Injector\Injector;
|
|
||||||
use SilverStripe\GraphQL\Scaffolding\Scaffolders\CRUD\ReadOne;
|
|
||||||
use SilverStripe\GraphQL\Scaffolding\StaticSchema;
|
|
||||||
use SilverStripe\ORM\DataList;
|
|
||||||
|
|
||||||
if (!class_exists(ReadOne::class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shim to make readOnePage work like GraphQL 4
|
|
||||||
*
|
|
||||||
* @internal Use GraphQL v4
|
|
||||||
* @deprecated 4.8..5.0 Use silverstripe/graphql:^4 functionality.
|
|
||||||
*/
|
|
||||||
class ReadOneResolver
|
|
||||||
{
|
|
||||||
public static function resolve($obj, array $args, array $context, ResolveInfo $info)
|
|
||||||
{
|
|
||||||
$idKey = StaticSchema::inst()->formatField('ID');
|
|
||||||
$id = $args['filter'][$idKey]['eq'];
|
|
||||||
$readOne = Injector::inst()->createWithArgs(ReadOne::class, ['Page']);
|
|
||||||
unset($args['filter']);
|
|
||||||
$args[$idKey] = $id;
|
|
||||||
return $readOne->resolve($obj, $args, $context, $info);
|
|
||||||
}
|
|
||||||
}
|
|
6
babel.config.json
Normal file
6
babel.config.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env",
|
||||||
|
"@babel/preset-react"
|
||||||
|
]
|
||||||
|
}
|
2
client/dist/js/SilverStripeNavigator.js
vendored
2
client/dist/js/SilverStripeNavigator.js
vendored
@ -1 +1 @@
|
|||||||
!function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/legacy/SilverStripeNavigator.js")}({"./client/src/legacy/SilverStripeNavigator.js":function(e,t,r){"use strict";function n(e){return document.getElementsByTagName("base")[0].href.replace("http://","").replace(/\//g,"_").replace(/\./g,"_")+e}var i=r(0),o=function(e){return e&&e.__esModule?e:{default:e}}(i);(0,o.default)(document).ready(function(){(0,o.default)("#switchView a.newWindow").on("click",function(e){return window.open(this.href,n(this.target)).focus(),!1}),(0,o.default)("#SilverStripeNavigatorLink").on("click",function(e){return(0,o.default)("#SilverStripeNavigatorLinkPopup").toggle(),!1}),(0,o.default)("#SilverStripeNavigatorLinkPopup a.close").on("click",function(e){return(0,o.default)("#SilverStripeNavigatorLinkPopup").hide(),!1}),(0,o.default)("#SilverStripeNavigatorLinkPopup input").on("focus",function(e){this.select()})})},0:function(e,t){e.exports=jQuery}});
|
!function(){"use strict";var e,t,i={311:function(e){e.exports=jQuery}},r={};function n(e){var t=r[e];if(void 0!==t)return t.exports;var o=r[e]={exports:{}};return i[e](o,o.exports,n),o.exports}(0,(t=(e=n(311))&&e.__esModule?e:{default:e}).default)(document).ready((function(){(0,t.default)("#switchView a.newWindow").on("click",(function(e){var t;return window.open(this.href,(t=this.target,document.getElementsByTagName("base")[0].href.replace("http://","").replace(/\//g,"_").replace(/\./g,"_")+t)).focus(),!1})),(0,t.default)("#SilverStripeNavigatorLink").on("click",(function(e){return(0,t.default)("#SilverStripeNavigatorLinkPopup").toggle(),!1})),(0,t.default)("#SilverStripeNavigatorLinkPopup a.close").on("click",(function(e){return(0,t.default)("#SilverStripeNavigatorLinkPopup").hide(),!1})),(0,t.default)("#SilverStripeNavigatorLinkPopup input").on("focus",(function(e){this.select()}))}))}();
|
2
client/dist/js/TinyMCE_sslink-anchor.js
vendored
2
client/dist/js/TinyMCE_sslink-anchor.js
vendored
@ -1 +1 @@
|
|||||||
!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/legacy/TinyMCE_sslink-anchor.js")}({"./client/src/legacy/TinyMCE_sslink-anchor.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(1),o=r(i),a=n(9),c=r(a),l=n(2),s=r(l),d=n(5),u=r(d),p=n(4),f=n(6),A=n(0),E=r(A),_=n(8),C=r(_),h=n(7),g=n(3),R=n("./client/src/state/anchorSelector/AnchorSelectorActions.js");c.default.addAction("sslink",{text:o.default._t("CMS.LINKLABEL_ANCHOR","Anchor on a page"),onclick:function(e){return e.execCommand("sslinkanchor")},priority:60},editorIdentifier).addCommandWithUrlTest("sslinkanchor",/^\[sitetree_link.+]#[^#\]]+$/);var O={init:function(e){e.addCommand("sslinkanchor",function(){var t=(0,E.default)("#"+e.id).entwine("ss"),n=Number((0,E.default)("#Form_EditForm_ID").val()||0),r=e.$("[id],[name]",e.getBody()).toArray().map(function(e){return e.id||e.name});ss.store.dispatch((0,R.updatedCurrentField)(n,r,e.id)),t.openLinkAnchorDialog()})}},m="insert-link__dialog-wrapper--anchor",T=(0,g.provideInjector)((0,h.createInsertLinkModal)("SilverStripe\\CMS\\Controllers\\CMSPageEditController","editorAnchorLink"));E.default.entwine("ss",function(e){e("textarea.htmleditor").entwine({openLinkAnchorDialog:function(){var t=e("#"+m);t.length||(t=e('<div id="'+m+'" />'),e("body").append(t)),t.addClass("insert-link__dialog-wrapper"),t.setElement(this),t.open()}}),e("#"+m).entwine({renderModal:function(t){var n=this,r=ss.store,i=ss.apolloClient,a=function(){return n.close()},c=function(){return n.handleInsert.apply(n,arguments)},l=this.getOriginalAttributes(),d=tinymce.activeEditor.selection,A=d.getContent()||"",E=d.getNode().tagName,_="A"!==E&&""===A.trim(),C=Number(e("#Form_EditForm_ID").val()||0);u.default.render(s.default.createElement(p.ApolloProvider,{client:i},s.default.createElement(f.Provider,{store:r},s.default.createElement(T,{isOpen:t,onInsert:c,onClosed:a,title:o.default._t("CMS.LINK_ANCHOR","Link to an anchor on a page"),bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--anchor",fileAttributes:l,identifier:"Admin.InsertLinkAnchorModal",requireLinkText:_,currentPageID:C}))),this[0])},buildAttributes:function(e){return{href:C.default.serialise({name:"sitetree_link",properties:{id:e.PageID}},!0)+(e.Anchor&&e.Anchor.length?"#"+e.Anchor:""),target:e.TargetBlank?"_blank":"",title:e.Description}},getOriginalAttributes:function(){var t=this.getElement().getEditor(),n=e(t.getSelectedNode()),r=(n.attr("href")||"").split("#");if(!r[0])return{};var i=C.default.match("sitetree_link",!1,r[0]);return i?{PageID:i.properties.id?parseInt(i.properties.id,10):0,Anchor:r[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}:{}}})}),tinymce.PluginManager.add("sslinkanchor",function(e){return O.init(e)}),t.default=O},"./client/src/state/anchorSelector/AnchorSelectorActionTypes.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={ANCHORSELECTOR_CURRENT_FIELD:"ANCHORSELECTOR_CURRENT_FIELD",ANCHORSELECTOR_UPDATED:"ANCHORSELECTOR_UPDATED",ANCHORSELECTOR_UPDATING:"ANCHORSELECTOR_UPDATING",ANCHORSELECTOR_UPDATE_FAILED:"ANCHORSELECTOR_UPDATE_FAILED"}},"./client/src/state/anchorSelector/AnchorSelectorActions.js":function(e,t,n){"use strict";function r(e){return{type:l.default.ANCHORSELECTOR_UPDATING,payload:{pageId:e}}}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return{type:l.default.ANCHORSELECTOR_UPDATED,payload:{pageId:e,anchors:t,cacheResult:n}}}function o(e,t,n){return{type:l.default.ANCHORSELECTOR_CURRENT_FIELD,payload:{pageId:e,anchors:t,fieldID:n}}}function a(e){return{type:l.default.ANCHORSELECTOR_UPDATE_FAILED,payload:{pageId:e}}}Object.defineProperty(t,"__esModule",{value:!0}),t.beginUpdating=r,t.updated=i,t.updatedCurrentField=o,t.updateFailed=a;var c=n("./client/src/state/anchorSelector/AnchorSelectorActionTypes.js"),l=function(e){return e&&e.__esModule?e:{default:e}}(c)},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=i18n},2:function(e,t){e.exports=React},3:function(e,t){e.exports=Injector},4:function(e,t){e.exports=ReactApollo},5:function(e,t){e.exports=ReactDom},6:function(e,t){e.exports=ReactRedux},7:function(e,t){e.exports=InsertLinkModal},8:function(e,t){e.exports=ShortcodeSerialiser},9:function(e,t){e.exports=TinyMCEActionRegistrar}});
|
!function(){"use strict";var e={964:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default={ANCHORSELECTOR_CURRENT_FIELD:"ANCHORSELECTOR_CURRENT_FIELD",ANCHORSELECTOR_UPDATED:"ANCHORSELECTOR_UPDATED",ANCHORSELECTOR_UPDATING:"ANCHORSELECTOR_UPDATING",ANCHORSELECTOR_UPDATE_FAILED:"ANCHORSELECTOR_UPDATE_FAILED"}},447:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.beginUpdating=function(e){return{type:i.default.ANCHORSELECTOR_UPDATING,payload:{pageId:e}}},t.updateFailed=function(e){return{type:i.default.ANCHORSELECTOR_UPDATE_FAILED,payload:{pageId:e}}},t.updated=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return{type:i.default.ANCHORSELECTOR_UPDATED,payload:{pageId:e,anchors:t,cacheResult:n}}},t.updatedCurrentField=function(e,t,n){return{type:i.default.ANCHORSELECTOR_CURRENT_FIELD,payload:{pageId:e,anchors:t,fieldID:n}}};var r,i=(r=n(964))&&r.__esModule?r:{default:r}},939:function(e){e.exports=ApolloClient},648:function(e){e.exports=Injector},595:function(e){e.exports=InsertLinkModal},363:function(e){e.exports=React},691:function(e){e.exports=ReactDomClient},624:function(e){e.exports=ReactRedux},265:function(e){e.exports=ShortcodeSerialiser},196:function(e){e.exports=TinyMCEActionRegistrar},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery}},t={};function n(r){var i=t[r];if(void 0!==i)return i.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,n),o.exports}!function(){var e=p(n(754)),t=p(n(196)),r=p(n(363)),i=n(691),o=n(939),a=n(624),d=p(n(311)),l=p(n(265)),s=n(595),u=n(648),c=n(447);function p(e){return e&&e.__esModule?e:{default:e}}const f="sslinkanchor";t.default.addAction("sslink",{text:e.default._t("CMS.LINKLABEL_ANCHOR","Anchor on a page"),onAction:e=>e.execCommand(f),priority:60},editorIdentifier).addCommandWithUrlTest(f,/^\[sitetree_link.+]#[^#\]]+$/);const E={init(e){e.addCommand(f,(()=>{const t=(0,d.default)(`#${e.id}`).entwine("ss"),n=Number((0,d.default)("#Form_EditForm_ID").val()||0),r=(0,d.default)(e.getBody()).find("[id],[name]").toArray().map((e=>e.id||e.name));ss.store.dispatch((0,c.updatedCurrentField)(n,r,e.id)),t.openLinkAnchorDialog()}))}},A="insert-link__dialog-wrapper--anchor",C=(0,u.provideInjector)((0,s.createInsertLinkModal)("SilverStripe\\CMS\\Controllers\\CMSPageEditController","editorAnchorLink"));d.default.entwine("ss",(t=>{t("textarea.htmleditor").entwine({openLinkAnchorDialog(){let e=t(`#${A}`);e.length||(e=t(`<div id="${A}" />`),t("body").append(e)),e.addClass("insert-link__dialog-wrapper"),e.setElement(this),e.open()}}),t(`#${A}`).entwine({ReactRoot:null,renderModal(n){var d=this;const l=ss.store,s=ss.apolloClient,u=this.getOriginalAttributes(),c=this.getElement().getEditor(),p=c.getInstance().selection,f=c.getSelection(),E="A"!==p.getNode().tagName&&""===f.trim(),A=Number(t("#Form_EditForm_ID").val()||0);let _=this.getReactRoot();_||(_=(0,i.createRoot)(this[0]),this.setReactRoot(_)),_.render(r.default.createElement(o.ApolloProvider,{client:s},r.default.createElement(a.Provider,{store:l},r.default.createElement(C,{isOpen:n,onInsert:function(){return d.handleInsert(...arguments)},onClosed:()=>this.close(),title:e.default._t("CMS.LINK_ANCHOR","Link to an anchor on a page"),bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--anchor",fileAttributes:u,identifier:"Admin.InsertLinkAnchorModal",requireLinkText:E,currentPageID:A}))))},buildAttributes(e){return{href:`${l.default.serialise({name:"sitetree_link",properties:{id:e.PageID}},!0)}${e.Anchor&&e.Anchor.length?`#${e.Anchor}`:""}`,target:e.TargetBlank?"_blank":"",title:e.Description}},getOriginalAttributes(){const e=this.getElement().getEditor(),n=t(e.getSelectedNode()),r=(n.attr("href")||"").split("#");if(!r[0])return{};const i=l.default.match("sitetree_link",!1,r[0]);return i?{PageID:i.properties.id?parseInt(i.properties.id,10):0,Anchor:r[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}:{}}})})),tinymce.PluginManager.add(f,(e=>E.init(e)))}()}();
|
2
client/dist/js/TinyMCE_sslink-internal.js
vendored
2
client/dist/js/TinyMCE_sslink-internal.js
vendored
@ -1 +1 @@
|
|||||||
!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/legacy/TinyMCE_sslink-internal.js")}({"./client/src/legacy/TinyMCE_sslink-internal.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(1),o=r(i),a=n(9),l=r(a),s=n(2),u=r(s),c=n(5),d=r(c),f=n(4),p=n(6),g=n(0),k=r(g),m=n(8),_=r(m),h=n(7),x=n(3);l.default.addAction("sslink",{text:o.default._t("CMS.LINKLABEL_PAGE","Page on this site"),onclick:function(e){return e.execCommand("sslinkinternal")},priority:90},editorIdentifier).addCommandWithUrlTest("sslinkinternal",/^\[sitetree_link.+]$/);var I={init:function(e){e.addCommand("sslinkinternal",function(){(0,k.default)("#"+e.id).entwine("ss").openLinkInternalDialog()})}},A="insert-link__dialog-wrapper--internal",C=(0,x.provideInjector)((0,h.createInsertLinkModal)("SilverStripe\\CMS\\Controllers\\CMSPageEditController","editorInternalLink"));k.default.entwine("ss",function(e){e("textarea.htmleditor").entwine({openLinkInternalDialog:function(){var t=e("#"+A);t.length||(t=e('<div id="'+A+'" />'),e("body").append(t)),t.addClass("insert-link__dialog-wrapper"),t.setElement(this),t.open()}}),e("#"+A).entwine({renderModal:function(e){var t=this,n=ss.store,r=ss.apolloClient,i=function(){return t.close()},a=function(){return t.handleInsert.apply(t,arguments)},l=this.getOriginalAttributes(),s=this.getRequireLinkText();d.default.render(u.default.createElement(f.ApolloProvider,{client:r},u.default.createElement(p.Provider,{store:n},u.default.createElement(C,{isOpen:e,onInsert:a,onClosed:i,title:o.default._t("CMS.LINK_PAGE","Link to a page"),bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--internal",fileAttributes:l,identifier:"Admin.InsertLinkInternalModal",requireLinkText:s}))),this[0])},getRequireLinkText:function(){var e=this.getElement().getEditor().getInstance().selection,t=e.getContent()||"";return"A"!==e.getNode().tagName&&""===t.trim()},buildAttributes:function(e){return{href:_.default.serialise({name:"sitetree_link",properties:{id:e.PageID}},!0)+(e.Anchor&&e.Anchor.length?"#"+e.Anchor:""),target:e.TargetBlank?"_blank":"",title:e.Description}},getOriginalAttributes:function(){var t=this.getElement().getEditor(),n=e(t.getSelectedNode()),r=(n.attr("href")||"").split("#");if(!r[0])return{};var i=_.default.match("sitetree_link",!1,r[0]);return i?{PageID:i.properties.id?parseInt(i.properties.id,10):0,Anchor:r[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}:{}}})}),tinymce.PluginManager.add("sslinkinternal",function(e){return I.init(e)}),t.default=I},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=i18n},2:function(e,t){e.exports=React},3:function(e,t){e.exports=Injector},4:function(e,t){e.exports=ReactApollo},5:function(e,t){e.exports=ReactDom},6:function(e,t){e.exports=ReactRedux},7:function(e,t){e.exports=InsertLinkModal},8:function(e,t){e.exports=ShortcodeSerialiser},9:function(e,t){e.exports=TinyMCEActionRegistrar}});
|
!function(){"use strict";var e={939:function(e){e.exports=ApolloClient},648:function(e){e.exports=Injector},595:function(e){e.exports=InsertLinkModal},363:function(e){e.exports=React},691:function(e){e.exports=ReactDomClient},624:function(e){e.exports=ReactRedux},265:function(e){e.exports=ShortcodeSerialiser},196:function(e){e.exports=TinyMCEActionRegistrar},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery}},t={};function n(i){var r=t[i];if(void 0!==r)return r.exports;var o=t[i]={exports:{}};return e[i](o,o.exports,n),o.exports}!function(){var e=u(n(754)),t=u(n(196)),i=u(n(363)),r=n(691),o=n(939),a=n(624),l=u(n(311)),s=u(n(265)),d=n(595),c=n(648);function u(e){return e&&e.__esModule?e:{default:e}}const p="sslinkinternal";t.default.addAction("sslink",{text:e.default._t("CMS.LINKLABEL_PAGE","Page on this site"),onAction:e=>e.execCommand(p),priority:90},editorIdentifier).addCommandWithUrlTest(p,/^\[sitetree_link.+]$/);const g={init(e){e.addCommand(p,(()=>{(0,l.default)(`#${e.id}`).entwine("ss").openLinkInternalDialog()}))}},f="insert-link__dialog-wrapper--internal",h=(0,c.provideInjector)((0,d.createInsertLinkModal)("SilverStripe\\CMS\\Controllers\\CMSPageEditController","editorInternalLink"));l.default.entwine("ss",(t=>{t("textarea.htmleditor").entwine({openLinkInternalDialog(){let e=t(`#${f}`);e.length||(e=t(`<div id="${f}" />`),t("body").append(e)),e.addClass("insert-link__dialog-wrapper"),e.setElement(this),e.open()}}),t(`#${f}`).entwine({ReactRoot:null,renderModal(t){var n=this;const l=ss.store,s=ss.apolloClient,d=this.getOriginalAttributes(),c=this.getRequireLinkText();let u=this.getReactRoot();u||(u=(0,r.createRoot)(this[0]),this.setReactRoot(u)),u.render(i.default.createElement(o.ApolloProvider,{client:s},i.default.createElement(a.Provider,{store:l},i.default.createElement(h,{isOpen:t,onInsert:function(){return n.handleInsert(...arguments)},onClosed:()=>this.close(),title:e.default._t("CMS.LINK_PAGE","Link to a page"),bodyClassName:"modal__dialog",className:"insert-link__dialog-wrapper--internal",fileAttributes:d,identifier:"Admin.InsertLinkInternalModal",requireLinkText:c}))))},getRequireLinkText(){const e=this.getElement().getEditor(),t=e.getInstance().selection,n=e.getSelection();return"A"!==t.getNode().tagName&&""===n.trim()},buildAttributes(e){return{href:`${s.default.serialise({name:"sitetree_link",properties:{id:e.PageID}},!0)}${e.Anchor&&e.Anchor.length?`#${e.Anchor}`:""}`,target:e.TargetBlank?"_blank":"",title:e.Description}},getOriginalAttributes(){const e=this.getElement().getEditor(),n=t(e.getSelectedNode()),i=(n.attr("href")||"").split("#");if(!i[0])return{};const r=s.default.match("sitetree_link",!1,i[0]);return r?{PageID:r.properties.id?parseInt(r.properties.id,10):0,Anchor:i[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}:{}}})})),tinymce.PluginManager.add(p,(e=>g.init(e)))}()}();
|
49
client/dist/js/bundle.js
vendored
49
client/dist/js/bundle.js
vendored
@ -1 +1,48 @@
|
|||||||
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle.js")}({"./client/src/boot/index.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var a=n("./client/src/boot/registerReducers.js"),o=r(a),i=n("./client/src/boot/registerComponents.js"),s=r(i);window.document.addEventListener("DOMContentLoaded",function(){(0,s.default)(),(0,o.default)()})},"./client/src/boot/registerComponents.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(3),o=r(a),i=n("./client/src/components/AnchorSelectorField/AnchorSelectorField.js"),s=r(i),l=n("./client/src/state/history/readOnePageQuery.js"),d=r(l),c=n("./client/src/state/history/rollbackPageMutation.js"),u=r(c);t.default=function(){o.default.component.register("AnchorSelectorField",s.default),o.default.transform("pages-history",function(e){e.component("HistoryViewer.pages-controller-cms-content",d.default,"PageHistoryViewer")}),o.default.transform("pages-history-revert",function(e){e.component("HistoryViewerToolbar.VersionedAdmin.HistoryViewer.SiteTree.HistoryViewerVersionDetail",u.default,"PageRevertMutation")})}},"./client/src/boot/registerReducers.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(3),o=r(a),i=n(12),s=n("./client/src/state/anchorSelector/AnchorSelectorReducer.js"),l=r(s);t.default=function(){o.default.reducer.register("cms",(0,i.combineReducers)({anchorSelector:l.default}))}},"./client/src/bundles/bundle.js":function(e,t,n){"use strict";n("./client/src/legacy/CMSMain.AddForm.js"),n("./client/src/legacy/CMSMain.EditForm.js"),n("./client/src/legacy/CMSMain.js"),n("./client/src/legacy/CMSMain.Tree.js"),n("./client/src/legacy/CMSPageHistoryController.js"),n("./client/src/legacy/RedirectorPage.js"),n("./client/src/legacy/SiteTreeURLSegmentField.js"),n("./client/src/boot/index.js")},"./client/src/components/AnchorSelectorField/AnchorSelectorField.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n=(0,b.formValueSelector)(t.formid,O.default),r=t&&t.data&&t.data.targetFieldName||"PageID",a=Number(n(e,r)||0),o=[],i=a?e.cms.anchorSelector.pages.find(function(e){return e.id===a}):null;!i||i.loadingState!==E.default.SUCCESS&&i.loadingState!==E.default.DIRTY&&i.loadingState!==E.default.FIELD_ONLY||(o=i.anchors);var s=null;return s=i?i.loadingState:a?E.default.DIRTY:E.default.SUCCESS,{pageId:a,anchors:o,loadingState:s}}function d(e){return{actions:{anchorSelector:(0,_.bindActionCreators)(w,e)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.ConnectedAnchorSelectorField=t.Component=void 0;var c=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),u=n(1),f=r(u),p=n(2),h=r(p),m=n(15),g=r(m),v=n(6),_=n(12),b=n(18),C=n(19),y=r(C),S=n("./client/src/state/anchorSelector/AnchorSelectorActions.js"),w=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(S),P=n("./client/src/state/anchorSelector/AnchorSelectorStates.js"),E=r(P),x=n(14),F=r(x),R=n(16),A=n(21),O=r(A),T=n(20),j=r(T),L=n(11),M=r(L),D=function(){return null},I=function(e){function t(e){o(this,t);var n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.handleChange=n.handleChange.bind(n),n.handleLoadingError=n.handleLoadingError.bind(n),n}return s(t,e),c(t,[{key:"componentDidMount",value:function(){this.ensurePagesLoaded()}},{key:"componentDidUpdate",value:function(e){this.props.pageId!==e.pageId&&this.ensurePagesLoaded()}},{key:"ensurePagesLoaded",value:function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.props;if(t.loadingState===E.default.UPDATING||t.loadingState===E.default.SUCCESS||!t.pageId)return Promise.resolve();var n=[];t.loadingState===E.default.FIELD_ONLY&&(n=this.props.anchors),t.actions.anchorSelector.beginUpdating(t.pageId);var r=t.data.endpoint.replace(/:id/,t.pageId);return(0,g.default)(r,{credentials:"same-origin"}).then(function(e){return e.json()}).then(function(e){var r=[].concat(a(new Set([].concat(a(e),a(n)))));return t.actions.anchorSelector.updated(t.pageId,r),r}).catch(function(n){t.actions.anchorSelector.updateFailed(t.pageId),e.handleLoadingError(n,t)})}},{key:"getDropdownOptions",value:function(){var e=this,t=this.props.anchors.map(function(e){return{value:e}});return this.props.value&&!this.props.anchors.find(function(t){return t===e.props.value})&&t.unshift({value:this.props.value}),t}},{key:"handleChange",value:function(e){"function"==typeof this.props.onChange&&this.props.onChange(e?e.value:"")}},{key:"handleLoadingError",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.props;if(t.onLoadingError===D)throw e;return t.onLoadingError({errors:[{value:e.message,type:"error"}]})}},{key:"render",value:function(){var e={id:this.props.id},t=(0,j.default)("anchorselectorfield",this.props.extraClass),n=this.getDropdownOptions(),r=this.props.value||"",a=f.default._t("CMS.ANCHOR_SELECT_OR_TYPE","Select or enter anchor");return h.default.createElement(R.Creatable,{searchable:!0,options:n,className:t,name:this.props.name,inputProps:e,onChange:this.handleChange,onBlurResetsInput:!0,value:r,placeholder:a,labelKey:"value"})}}]),t}(y.default);I.propTypes={extraClass:M.default.string,id:M.default.string,name:M.default.string.isRequired,onChange:M.default.func,value:M.default.string,attributes:M.default.oneOfType([M.default.object,M.default.array]),pageId:M.default.number,anchors:M.default.array,loadingState:M.default.oneOf(Object.keys(E.default).map(function(e){return E.default[e]})),onLoadingError:M.default.func,data:M.default.shape({endpoint:M.default.string,targetFieldName:M.default.string})},I.defaultProps={value:"",extraClass:"",onLoadingError:D,attributes:{}};var k=(0,v.connect)(l,d)(I);t.Component=I,t.ConnectedAnchorSelectorField=k,t.default=(0,F.default)(k)},"./client/src/legacy/CMSMain.AddForm.js":function(e,t,n){"use strict";var r=n(0);(function(e){return e&&e.__esModule?e:{default:e}})(r).default.entwine("ss",function(e){e(".TreeDropdownField").entwine({OldValue:null}),e("#Form_AddForm_ParentID_Holder .treedropdownfield").entwine({onmatch:function(){this._super(),e(".cms-add-form").updateTypeList()}}),e(".cms-add-form .parent-mode :input").entwine({onclick:function(e){var t=this.closest("form").find("#Form_AddForm_ParentID_Holder .TreeDropdownField");"top"==this.val()?(t.setOldValue(t.getValue()),t.setValue(0)):(t.setValue(t.getOldValue()||0),t.setOldValue(null)),t.refresh(),t.trigger("change")}}),e(".cms-add-form").entwine({ParentCache:{},onadd:function(){var t=this;this.find("#Form_AddForm_ParentID_Holder .TreeDropdownField").on("change",function(){t.updateTypeList()}),this.find(".SelectionGroup.parent-mode").on("change",function(){t.updateTypeList()}),"top"==e(".cms-add-form .parent-mode :input").val()&&this.updateTypeList()},loadCachedChildren:function(e){var t=this.getParentCache();return void 0!==t[e]?t[e]:null},saveCachedChildren:function(e,t){var n=this.getParentCache();n[e]=t,this.setParentCache(n)},updateTypeList:function(){var t=this.data("hints"),n=this.find("#Form_AddForm_ParentID"),r=this.find("input[name=ParentModeField]:checked").val(),a=n.data("metadata"),o="child"===r?n.getValue():null,i=a?a.ClassName:null,s=i&&"child"===r&&o?i:"Root",l=void 0!==t[s]?t[s]:null,d=this,c=l&&void 0!==l.defaultChild?l.defaultChild:null,u=[];if(o){if(this.hasClass("loading"))return;return this.addClass("loading"),null!==(u=this.loadCachedChildren(o))?(this.updateSelectionFilter(u,c),void this.removeClass("loading")):(e.ajax({url:d.data("childfilter"),data:{ParentID:o},success:function(e){d.saveCachedChildren(o,e),d.updateSelectionFilter(e,c)},complete:function(){d.removeClass("loading")}}),!1)}u=l&&void 0!==l.disallowedChildren?l.disallowedChildren:[],this.updateSelectionFilter(u,c)},updateSelectionFilter:function(t,n){var r=this.find("#Form_AddForm_PageType div.radio.selected")[0],a=!1,o=null;if(this.find("#Form_AddForm_PageType div.radio").each(function(n,i){var s=e(this).find("input").val(),l=-1===e.inArray(s,t);i===r&&l&&(a=!0),e(this).setEnabled(l),l||e(this).setSelected(!1),o=null===o?l:o&&l}),a)var i=e(r).parents("li:first");else if(n)var i=this.find("#Form_AddForm_PageType div.radio input[value="+n+"]").parents("li:first");else var i=this.find("#Form_AddForm_PageType div.radio:not(.disabled):first");i.setSelected(!0),i.siblings().setSelected(!1),this.find("#Form_AddForm_PageType div.radio:not(.disabled)").length?this.find("button[name=action_doAdd]").removeAttr("disabled"):this.find("button[name=action_doAdd]").attr("disabled","disabled"),this.find(".message-restricted")[o?"hide":"show"]()}}),e(".cms-add-form #Form_AddForm_PageType div.radio").entwine({onclick:function(e){this.setSelected(!0)},setSelected:function(e){var t=this.find("input");e&&!t.is(":disabled")?(this.siblings().setSelected(!1),this.toggleClass("selected",!0),t.prop("checked",!0)):(this.toggleClass("selected",!1),t.prop("checked",!1))},setEnabled:function(t){e(this).toggleClass("disabled",!t),t?e(this).find("input").removeAttr("disabled"):e(this).find("input").attr("disabled","disabled").removeAttr("checked")}}),e(".cms-content-addpage-button").entwine({onclick:function(t){var n,r=e(".cms-tree"),a=e(".cms-list"),o=0;if(r.is(":visible")){var i=r.jstree("get_selected");o=i?e(i[0]).data("id"):null}else{var s=a.find('input[name="Page[GridState]"]').val();s&&(o=parseInt(JSON.parse(s).ParentID,10))}var l,d={selector:this.data("targetPanel"),pjax:this.data("pjax")};o?(n=this.data("extraParams")?this.data("extraParams"):"",l=e.path.addSearchParams(i18n.sprintf(this.data("urlAddpage"),o),n)):l=this.attr("href"),e(".cms-container").loadPanel(l,null,d),t.preventDefault(),this.blur()}})})},"./client/src/legacy/CMSMain.EditForm.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,n){function r(a,o){try{var i=t[a](o),s=i.value}catch(e){return void n(e)}if(!i.done)return Promise.resolve(s).then(function(e){r("next",e)},function(e){r("throw",e)});e(s)}return r("next")})}}var o=n(0),i=r(o),s=n(1),l=r(s),d=n("./node_modules/@silverstripe/reactstrap-confirm/dist/index.js"),c=r(d);i.default.entwine("ss",function(e){e(".cms-edit-form :input#Form_EditForm_ClassName").entwine({onchange:function(){alert(l.default._t("CMS.ALERTCLASSNAME"))}}),e(".cms-edit-form input[name=Title]").entwine({onmatch:function(){var t=this;t.data("OrigVal",t.val());var n=t.closest("form"),r=e("input:text[name=URLSegment]",n),a=e("input[name=LiveLink]",n);r.length>0&&(t._addActions(),this.on("change",function(n){var o=t.data("OrigVal"),i=t.val();t.data("OrigVal",i),0===r.val().indexOf(r.data("defaultUrl"))&&""==a.val()?t.updateURLSegment(i):e(".update",t.parent()).show().parent(".form__field-holder").addClass("input-group"),t.updateRelatedFields(i,o),t.updateBreadcrumbLabel(i)})),this._super()},onunmatch:function(){this._super()},updateRelatedFields:function(t,n){this.parents("form").find("input[name=MetaTitle], input[name=MenuTitle]").each(function(){var r=e(this);r.val()==n&&(r.val(t),r.updatedRelatedFields&&r.updatedRelatedFields())})},updateURLSegment:function(t){var n=e("input:text[name=URLSegment]",this.closest("form")),r=n.closest(".field.urlsegment"),a=e(".update",this.parent());r.update(t),a.is(":visible")&&a.hide().parent(".form__field-holder").removeClass("input-group")},updateBreadcrumbLabel:function(t){var n=(e(".cms-edit-form input[name=ID]").val(),e("span.cms-panel-link.crumb"));t&&""!=t&&n.text(t)},_addActions:function(){var t,n=this;t=e("<button />",{class:"update btn btn-outline-secondary form__field-update-url",text:l.default._t("CMS.UpdateURL"),type:"button",click:function(e){e.preventDefault(),n.updateURLSegment(n.val())}}),t.insertAfter(n),t.hide()}}),e(".cms-edit-form .parentTypeSelector").entwine({onmatch:function(){var e=this;this.find(":input[name=ParentType]").on("click",function(t){e._toggleSelection(t)}),this.find(".TreeDropdownField").on("change",function(t){e._changeParentId(t)}),this._changeParentId(),this._toggleSelection(),this._super()},onunmatch:function(){this._super()},_toggleSelection:function(t){var n=this.find(":input[name=ParentType]:checked").val(),r=this.find("#Form_EditForm_ParentID_Holder");"root"==n?this.find(":input[name=ParentID]").val(0):this.find(":input[name=ParentID]").val(this.find("#Form_EditForm_ParentType_subpage").data("parentIdValue")),"root"!=n?r.slideDown(400,function(){e(this).css("overflow","visible")}):r.slideUp()},_changeParentId:function(e){var t=this.find(":input[name=ParentID]").val();this.find("#Form_EditForm_ParentType_subpage").data("parentIdValue",t)}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_doRollback, .cms-edit-form .btn-toolbar #Form_EditForm_action_rollback").entwine({onclick:function(e){if(this.is(":disabled"))return e.preventDefault(),!1;var t=this.parents("form:first").find(":input[name=Version]").val(),n=t?l.default.sprintf(l.default._t("CMS.RollbackToVersion","Do you really want to roll back to version #%s of this page?"),t):l.default._t("CMS.ConfirmRestoreFromLive","Are you sure you want to revert draft to when the page was last published?");return confirm(n)?(this.parents("form:first").addClass("loading"),this._super(e)):(e.preventDefault(),!1)}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_archive:not(.homepage-warning)").entwine({onclick:function(e){var t=this.parents("form:first"),n="";return n=t.find("input[name=ArchiveWarningMessage]").val().replace(/\\n/g,"\n"),!!confirm(n)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_restore").entwine({onclick:function(e){var t=this.parents("form:first"),n=t.find(":input[name=Version]").val(),r="",a=this.data("toRoot");return r=l.default.sprintf(l.default._t(a?"CMS.RestoreToRoot":"CMS.Restore"),n),!!confirm(r)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_unpublish:not(.homepage-warning)").entwine({onclick:function(e){var t=this.parents("form:first"),n=t.find(":input[name=Version]").val(),r="";return r=l.default.sprintf(l.default._t("CMS.Unpublish"),n),!!confirm(r)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form.changed").entwine({onmatch:function(t){this.find("button[data-text-alternate]").each(function(){var t=e(this),n=t.find(".btn__title"),r=t.data("textAlternate");r&&(t.data("textStandard",n.text()),n.text(r));var a=t.data("btnAlternate");a&&(t.data("btnStandard",t.attr("class")),t.attr("class",a),t.removeClass("btn-outline-secondary").addClass("btn-primary"));var o=t.data("btnAlternateAdd");o&&t.addClass(o);var i=t.data("btnAlternateRemove");i&&t.removeClass(i)}),this._super(t)},onunmatch:function(t){this.find("button[data-text-alternate]").each(function(){var t=e(this),n=t.find(".btn__title"),r=t.data("textStandard");r&&n.text(r);var a=t.data("btnStandard");a&&(t.attr("class",a),t.addClass("btn-outline-secondary").removeClass("btn-primary"));var o=t.data("btnAlternateAdd");o&&t.removeClass(o);var i=t.data("btnAlternateRemove");i&&t.addClass(i)}),this._super(t)}}),e(".cms-edit-form .btn-toolbar button[name=action_publish]").entwine({onbuttonafterrefreshalternate:function(){this.data("showingAlternate")?(this.addClass("btn-primary"),this.removeClass("btn-secondary")):(this.removeClass("btn-primary"),this.addClass("btn-secondary"))}}),e(".cms-edit-form .btn-toolbar button[name=action_save]").entwine({onbuttonafterrefreshalternate:function(){this.data("showingAlternate")?(this.addClass("btn-primary"),this.removeClass("btn-secondary")):(this.removeClass("btn-primary"),this.addClass("btn-secondary"))}}),e('.cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked').entwine({onmatch:function(){this.redraw(),this._super()},onunmatch:function(){this._super()},redraw:function(){var t=e(".cms-edit-form.CMSPageSettingsController #Form_EditForm_ParentID_Holder");"Form_EditForm_ParentType_root"==e(this).attr("id")?t.slideUp():t.slideDown()},onclick:function(){this.redraw()}}),"Form_EditForm_ParentType_root"==e('.cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked').attr("id")&&e(".cms-edit-form.CMSPageSettingsController #Form_EditForm_ParentID_Holder").hide();var t=!1;e(".cms-edit-form .btn-toolbar #Form_EditForm_action_unpublish.homepage-warning,.cms-edit-form .btn-toolbar #Form_EditForm_action_archive.homepage-warning,#Form_EditForm_URLSegment_Holder.homepage-warning .btn.update").entwine({onclick:function(){function e(e){return n.apply(this,arguments)}var n=a(regeneratorRuntime.mark(function e(n){var r;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!t){e.next=2;break}return e.abrupt("return",this._super(n));case 2:return n.stopPropagation(),r=l.default._t("CMS.RemoveHomePageWarningMessage","Warning: This page is the home page. By changing the URL segment visitors will not be able to view it."),e.next=6,(0,c.default)(r,{title:l.default._t("CMS.RemoveHomePageWarningTitle","Remove your home page?"),confirmLabel:l.default._t("CMS.RemoveHomePageWarningLabel","Remove"),confirmColor:"danger"});case 6:if(!e.sent){e.next=10;break}t=!0,this.trigger("click"),t=!1;case 10:return e.abrupt("return",!1);case 11:case"end":return e.stop()}},e,this)}));return e}()})})},"./client/src/legacy/CMSMain.Tree.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,n){function r(a,o){try{var i=t[a](o),s=i.value}catch(e){return void n(e)}if(!i.done)return Promise.resolve(s).then(function(e){r("next",e)},function(e){r("throw",e)});e(s)}return r("next")})}}var o=n(0),i=r(o),s=n(1),l=r(s),d=n("./node_modules/@silverstripe/reactstrap-confirm/dist/index.js"),c=r(d);i.default.entwine("ss.tree",function(e){e(".cms-tree").entwine({fromDocument:{"oncontext_show.vakata":function(e){this.adjustContextClass()}},adjustContextClass:function(){var t=e("#vakata-contextmenu").find("ul ul");t.each(function(n){var r="1",a=e(t[n]).find("li").length;a>20?r="3":a>10&&(r="2"),e(t[n]).addClass("vakata-col-"+r).removeClass("right"),e(t[n]).find("li").on("mouseenter",function(t){e(this).parent("ul").removeClass("right")})})},showListViewFor:function(t){localStorage.setItem("ss.pages-view-type","listview");var n=this.closest(".cms-content-view"),r=n.data("url-listviewroot"),a=e.path.addSearchParams(r,{ParentID:t}),o=e("base").attr("href")||"";window.location.assign(o+a)},getTreeConfig:function(){var t=this,n=this._super();return this.getHints(),n.plugins.push("contextmenu"),n.contextmenu={items:function(n){var r={edit:{label:n.hasClass("edit-disabled")?l.default._t("CMS.EditPage","Edit page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"):l.default._t("CMS.ViewPage","View page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(l.default.sprintf(t.data("urlEditpage"),n.data("id")))}}};n.hasClass("nochildren")||(r.showaslist={label:l.default._t("CMS.ShowAsList"),action:function(e){t.showListViewFor(e.data("id"))}});var a=(n.data("pagetype"),n.data("id")),o=n.find(">a .item").data("allowedchildren"),i={},s=!1;return e.each(o,function(n,r){s=!0,i["allowedchildren-"+r.ClassName]={label:'<span class="jstree-pageicon '+r.IconClass+'"></span>'+r.Title,_class:"class-"+r.ClassName.replace(/[^a-zA-Z0-9\-_:.]+/g,"_"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(l.default.sprintf(t.data("urlAddpage"),a,r.ClassName),t.data("extraParams")))}}}),s&&(r.addsubpage={label:l.default._t("CMS.AddSubPage","Add page under this page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"),submenu:i}),n.hasClass("edit-disabled")||(r.duplicate={label:l.default._t("CMS.Duplicate"),submenu:[{label:l.default._t("CMS.ThisPageOnly"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(l.default.sprintf(t.data("urlDuplicate"),n.data("id")),t.data("extraParams")))}},{label:l.default._t("CMS.ThisPageAndSubpages"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(l.default.sprintf(t.data("urlDuplicatewithchildren"),n.data("id")),t.data("extraParams")))}}]}),r}},n},canMove:function(){function e(e){return t.apply(this,arguments)}var t=a(regeneratorRuntime.mark(function e(t){var n,r,a,o;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.rslt.o.find(".homepage").first().length>0){e.next=3;break}return e.abrupt("return",!0);case 3:if(r=t.rslt.op.data("id"),a=t.rslt.np.data("id"),r!==a){e.next=7;break}return e.abrupt("return",!0);case 7:return o=l.default._t("CMS.RemoveHomePageWarningMessage","Warning: This page is the home page. By changing the URL segment visitors will not be able to view it."),e.next=10,(0,c.default)(o,{title:l.default._t("CMS.RemoveHomePageWarningTitle","Remove your home page?"),confirmLabel:l.default._t("CMS.RemoveHomePageWarningLabel","Remove"),confirmColor:"danger"});case 10:return e.abrupt("return",e.sent);case 11:case"end":return e.stop()}},e,this)}));return e}()}),e(".cms-tree a.jstree-clicked").entwine({onmatch:function(){var e=this,t=e.parents(".cms-tree-view-sidebar");if(e.offset().top<0||e.offset().top>t.height()-e.height()){var n=e.parent();n.prev().length&&(n=n.prev()),n.get(0).scrollIntoView()}}}),e(".cms-tree-filtered .clear-filter").entwine({onclick:function(){window.location=location.protocol+"//"+location.host+location.pathname}}),e(".cms-tree .subtree-list-link").entwine({onclick:function(e){e.preventDefault(),this.closest(".cms-tree").showListViewFor(this.data("id"))}})})},"./client/src/legacy/CMSMain.js":function(e,t,n){"use strict";var r=n(0);(function(e){return e&&e.__esModule?e:{default:e}})(r).default.entwine("ss",function(e){e(".cms-content-header-info").entwine({"from .cms-panel":{ontoggle:function(e){var t=this.closest(".cms-content").find(e.target);0!==t.length&&this.parent()[t.hasClass("collapsed")?"addClass":"removeClass"]("collapsed")}}}),e(".cms-panel-deferred.cms-content-view").entwine({onadd:function(){if(!this.data("no-ajax")){var e=localStorage.getItem("ss.pages-view-type")||"treeview";this.closest(".cms-content-tools").length>0&&(e="treeview");var t=this.data("url-"+e),n=localStorage.getItem("ss.pages-view-filtered");"string"==typeof n&&"false"===n.toLowerCase()&&(n=!1),localStorage.setItem("ss.pages-view-filtered",!1),this.data("deferredNoCache",n||"listview"===e),this.data("url",t+location.search),this._super()}}}),e(".js-injector-boot .search-holder--cms").entwine({search:function(e){localStorage.setItem("ss.pages-view-filtered",!0),this._super(e)}}),e(".cms .page-view-link").entwine({onclick:function(t){t.preventDefault();var n=e(this).data("view"),r=this.closest(".cms-content-view"),a=r.data("url-"+n),o=0!==r.closest(".cms-content-tools").length;if(localStorage.setItem("ss.pages-view-type",n),o&&"listview"===n){var i=e("base").attr("href")||"";return void window.location.assign(i+r.data("url-listviewroot"))}r.data("url",a+location.search),r.redraw()}}),e(".cms .cms-clear-filter").entwine({onclick:function(t){t.preventDefault(),window.location=e(this).prop("href")}}),e(".cms-content-toolbar").entwine({onmatch:function(){var t=this;this._super(),e.each(this.find(".cms-actions-buttons-row .tool-button"),function(){var n=e(this),r=n.data("toolid");n.hasClass("active"),void 0!==r&&(n.data("active",!1).removeClass("active"),e("#"+r).hide(),t.bindActionButtonEvents(n))})},onunmatch:function(){var t=this;this._super(),e.each(this.find(".cms-actions-buttons-row .tool-button"),function(){var n=e(this);t.unbindActionButtonEvents(n)})},bindActionButtonEvents:function(e){var t=this;e.on("click.cmsContentToolbar",function(n){t.showHideTool(e)})},unbindActionButtonEvents:function(e){e.off(".cmsContentToolbar")},showHideTool:function(t){var n=t.data("active"),r=t.data("toolid"),a=e("#"+r);e.each(this.find(".cms-actions-buttons-row .tool-button"),function(){var t=e(this),n=e("#"+t.data("toolid"));t.data("toolid")!==r&&(n.hide(),t.data("active",!1))}),t[n?"removeClass":"addClass"]("active"),a[n?"hide":"show"](),t.data("active",!n)}})})},"./client/src/legacy/CMSPageHistoryController.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var a=n(0),o=r(a),i=n(1),s=r(i);o.default.entwine("ss",function(e){e("#Form_VersionsForm").entwine({onmatch:function(){this._super()},onunmatch:function(){this._super()},onsubmit:function(t){t.preventDefault();var n=this.find(":input[name=ID]").val();if(!n)return!1;var r=null,a=null,o=null,i=this.find(":input[name=CompareMode]").is(":checked"),l=this.find("table input[type=checkbox]").filter(":checked");if(i){if(2!==l.length)return!1;a=l.eq(0).val(),o=l.eq(1).val(),r=s.default.sprintf(this.data("linkTmplCompare"),n,o,a)}else a=l.eq(0).val(),r=s.default.sprintf(this.data("linkTmplShow"),n,a);return e(".cms-container").loadPanel(r,"",{pjax:"CurrentForm"}),!0}}),e("#Form_VersionsForm input[name=ShowUnpublished]").entwine({onmatch:function(){this.toggle(),this._super()},onunmatch:function(){this._super()},onchange:function(){this.toggle()},toggle:function(){var t=e(this),n=t.parents("form").find("tr[data-published=false]");t.attr("checked")?n.removeClass("ui-helper-hidden").show():n.addClass("ui-helper-hidden").hide()._unselect()}}),e("#Form_VersionsForm tbody tr").entwine({onclick:function(){var e=this.parents("form").find(":input[name=CompareMode]").attr("checked"),t=this.siblings(".active");return e&&this.hasClass("active")?void this._unselect():e?t.length>1?void alert(s.default._t("CMS.ONLYSELECTTWO","You can only compare two versions at this time.")):(this._select(),void(1===t.length&&this.parents("form").submit())):(this._select(),t._unselect(),void this.parents("form").submit())},_unselect:function(){this.get(0).classList.remove("active"),this.find(":input[type=checkbox][checked]").attr("checked",!1)},_select:function(){this.addClass("active"),this.find(":input[type=checkbox]").attr("checked",!0)}})})},"./client/src/legacy/RedirectorPage.js":function(e,t,n){"use strict";var r=n(0);(function(e){return e&&e.__esModule?e:{default:e}})(r).default.entwine("ss",function(e){e("#Form_EditForm_RedirectionType input").entwine({onmatch:function(){e(this).attr("checked")&&this.toggle(),this._super()},onunmatch:function(){this._super()},onclick:function(){this.toggle()},toggle:function(){"Internal"==e(this).attr("value")?(e("#Form_EditForm_ExternalURL_Holder").hide(),e("#Form_EditForm_LinkToID_Holder").show(),e("#Form_EditForm_LinkToFile_Holder").hide()):"External"==e(this).attr("value")?(e("#Form_EditForm_ExternalURL_Holder").show(),e("#Form_EditForm_LinkToID_Holder").hide(),e("#Form_EditForm_LinkToFile_Holder").hide()):(e("#Form_EditForm_LinkToFile_Holder").show(),e("#Form_EditForm_ExternalURL_Holder").hide(),e("#Form_EditForm_LinkToID_Holder").hide())}})})},"./client/src/legacy/SiteTreeURLSegmentField.js":function(e,t,n){"use strict";var r=n(0);(function(e){return e&&e.__esModule?e:{default:e}})(r).default.entwine("ss",function(e){e(".field.urlsegment:not(.readonly)").entwine({MaxPreviewLength:55,Ellipsis:"...",onmatch:function(){this.find(":text").length&&this.toggleEdit(!1),this.redraw(),this._super()},redraw:function(){var e=this.find(":text"),t=decodeURI(e.data("prefix")+e.val()),n=t;t.length>this.getMaxPreviewLength()&&(n=this.getEllipsis()+t.substr(t.length-this.getMaxPreviewLength(),t.length)),this.find(".URL-link").attr("href",encodeURI(t+e.data("suffix"))).text(n)},toggleEdit:function(e){var t=this.find(":text");this.find(".preview-holder")[e?"hide":"show"](),this.find(".edit-holder")[e?"show":"hide"](),e&&(t.data("origval",t.val()),t.focus())},update:function(){var e=this,t=this.find(":text"),n=t.data("origval"),r=arguments[0],a=r&&""!==r?r:t.val();n!=a?(this.addClass("loading"),this.suggest(a,function(n){t.val(decodeURIComponent(n.value)),e.toggleEdit(!1),e.removeClass("loading"),e.redraw()})):(this.toggleEdit(!1),this.redraw())},cancel:function(){var e=this.find(":text");e.val(e.data("origval")),this.toggleEdit(!1)},suggest:function(t,n){var r=this,a=r.find(":text"),o=e.path.parseUrl(r.closest("form").attr("action")),i=o.hrefNoSearch+"/field/"+a.attr("name")+"/suggest/?value="+encodeURIComponent(t);o.search&&(i+="&"+o.search.replace(/^\?/,"")),e.ajax({url:i,success:function(e){n.apply(this,arguments)},error:function(e,t){e.statusText=e.responseText},complete:function(){r.removeClass("loading")}})}}),e(".field.urlsegment .text").entwine({onkeydown:function(e){13===e.keyCode&&(e.preventDefault(),this.closest(".field").update())}}),e(".field.urlsegment .edit").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").toggleEdit(!0)}}),e(".field.urlsegment .update").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").update()}}),e(".field.urlsegment .cancel").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").cancel()}})})},"./client/src/state/anchorSelector/AnchorSelectorActionTypes.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={ANCHORSELECTOR_CURRENT_FIELD:"ANCHORSELECTOR_CURRENT_FIELD",ANCHORSELECTOR_UPDATED:"ANCHORSELECTOR_UPDATED",ANCHORSELECTOR_UPDATING:"ANCHORSELECTOR_UPDATING",ANCHORSELECTOR_UPDATE_FAILED:"ANCHORSELECTOR_UPDATE_FAILED"}},"./client/src/state/anchorSelector/AnchorSelectorActions.js":function(e,t,n){"use strict";function r(e){return{type:l.default.ANCHORSELECTOR_UPDATING,payload:{pageId:e}}}function a(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return{type:l.default.ANCHORSELECTOR_UPDATED,payload:{pageId:e,anchors:t,cacheResult:n}}}function o(e,t,n){return{type:l.default.ANCHORSELECTOR_CURRENT_FIELD,payload:{pageId:e,anchors:t,fieldID:n}}}function i(e){return{type:l.default.ANCHORSELECTOR_UPDATE_FAILED,payload:{pageId:e}}}Object.defineProperty(t,"__esModule",{value:!0}),t.beginUpdating=r,t.updated=a,t.updatedCurrentField=o,t.updateFailed=i;var s=n("./client/src/state/anchorSelector/AnchorSelectorActionTypes.js"),l=function(e){return e&&e.__esModule?e:{default:e}}(s)},"./client/src/state/anchorSelector/AnchorSelectorReducer.js":function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function o(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:f,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,n=function(n,r){var o=t.payload.pageId;return(0,s.default)({pages:[].concat(a(e.pages.filter(function(e){return e.id!==o})),[{id:o,loadingState:n,anchors:r}]).sort(function(e,t){return e.id-t.id})})};switch(t.type){case d.default.ANCHORSELECTOR_UPDATING:return n(u.default.UPDATING,[]);case d.default.ANCHORSELECTOR_UPDATED:var r=t.payload,o=r.anchors,i=r.cacheResult,l=u.default.SUCCESS,c=u.default.DIRTY;return n(i?l:c,o);case d.default.ANCHORSELECTOR_CURRENT_FIELD:var p=t.payload.anchors;return n(u.default.FIELD_ONLY,p);case d.default.ANCHORSELECTOR_UPDATE_FAILED:return n(u.default.FAILED,[]);default:return e}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=o;var i=n(13),s=r(i),l=n("./client/src/state/anchorSelector/AnchorSelectorActionTypes.js"),d=r(l),c=n("./client/src/state/anchorSelector/AnchorSelectorStates.js"),u=r(c),f=(0,s.default)({pages:[]})},"./client/src/state/anchorSelector/AnchorSelectorStates.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={SUCCESS:"SUCCESS",DIRTY:"DIRTY",FIELD_ONLY:"FIELD_ONLY",UPDATING:"UPDATING",FAILED:"FAILED"}},"./client/src/state/history/readOnePageQuery.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.config=t.query=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},a=function(e,t){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}(["\nquery ReadHistoryViewerPage ($page_id: ID!, $limit: Int!, $offset: Int!) {\n readOnePage(\n versioning: {\n mode: ALL_VERSIONS\n },\n filter: {\n id: { eq: $page_id }\n }\n ) {\n id\n versions (limit: $limit, offset: $offset, sort: {\n version: DESC\n }) {\n pageInfo {\n totalCount\n }\n nodes {\n version\n absoluteLink\n author {\n firstName\n surname\n }\n publisher {\n firstName\n surname\n }\n deleted\n draft\n published\n liveVersion\n latestDraftVersion\n lastEdited\n }\n }\n }\n}\n"],["\nquery ReadHistoryViewerPage ($page_id: ID!, $limit: Int!, $offset: Int!) {\n readOnePage(\n versioning: {\n mode: ALL_VERSIONS\n },\n filter: {\n id: { eq: $page_id }\n }\n ) {\n id\n versions (limit: $limit, offset: $offset, sort: {\n version: DESC\n }) {\n pageInfo {\n totalCount\n }\n nodes {\n version\n absoluteLink\n author {\n firstName\n surname\n }\n publisher {\n firstName\n surname\n }\n deleted\n draft\n published\n liveVersion\n latestDraftVersion\n lastEdited\n }\n }\n }\n}\n"]),o=n(4),i=n(10),s=function(e){return e&&e.__esModule?e:{default:e}}(i),l=(0,s.default)(a),d={options:function(e){var t=e.recordId,n=e.limit;return{variables:{limit:n,offset:((e.page||1)-1)*n,page_id:t},fetchPolicy:"network-only"}},props:function(e){var t=e.data,n=t.error,a=t.refetch,o=t.readOnePage,i=t.loading,s=e.ownProps,l=s.actions,d=void 0===l?{versions:{}}:l,c=s.limit,u=s.recordId,f=o||null,p=n&&n.graphQLErrors&&n.graphQLErrors.map(function(e){return e.message});return{loading:i||!f,versions:f,graphQLErrors:p,actions:r({},d,{versions:r({},f,{goToPage:function(e){a({offset:((e||1)-1)*c,limit:c,page_id:u})}})})}}};t.query=l,t.config=d,t.default=(0,o.graphql)(l,d)},"./client/src/state/history/rollbackPageMutation.js":function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.config=t.mutation=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},a=function(e,t){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}(["\nmutation rollbackPage($id:ID!, $toVersion:Int!) {\n rollbackPage(\n id: $id\n toVersion: $toVersion\n ) {\n id\n }\n}\n"],["\nmutation rollbackPage($id:ID!, $toVersion:Int!) {\n rollbackPage(\n id: $id\n toVersion: $toVersion\n ) {\n id\n }\n}\n"]),o=n(4),i=n(10),s=function(e){return e&&e.__esModule?e:{default:e}}(i),l=(0,s.default)(a),d={props:function(e){var t=e.mutate,n=e.ownProps.actions,a=function(e,n){return t({variables:{id:e,toVersion:n}})};return{actions:r({},n,{rollbackPage:a,revertToVersion:a})}},options:{refetchQueries:["ReadHistoryViewerPage"]}};t.mutation=l,t.config=d,t.default=(0,o.graphql)(l,d)},"./node_modules/@babel/runtime/helpers/extends.js":function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},e.exports.default=e.exports,e.exports.__esModule=!0,n.apply(this,arguments)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@babel/runtime/helpers/inheritsLoose.js":function(e,t,n){function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,a(e,t)}var a=n("./node_modules/@babel/runtime/helpers/setPrototypeOf.js");e.exports=r,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@babel/runtime/helpers/interopRequireDefault.js":function(e,t){function n(e){return e&&e.__esModule?e:{default:e}}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@babel/runtime/helpers/interopRequireWildcard.js":function(e,t,n){function r(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(r=function(e){return e?n:t})(e)}function a(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==o(e)&&"function"!=typeof e)return{default:e};var n=r(t);if(n&&n.has(e))return n.get(e);var a={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var s in e)if("default"!==s&&Object.prototype.hasOwnProperty.call(e,s)){var l=i?Object.getOwnPropertyDescriptor(e,s):null;l&&(l.get||l.set)?Object.defineProperty(a,s,l):a[s]=e[s]}return a.default=e,n&&n.set(e,a),a}var o=n("./node_modules/@babel/runtime/helpers/typeof.js").default;e.exports=a,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@babel/runtime/helpers/setPrototypeOf.js":function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e.exports.default=e.exports,e.exports.__esModule=!0,n(t,r)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@babel/runtime/helpers/typeof.js":function(e,t){function n(t){"@babel/helpers - typeof";return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?(e.exports=n=function(e){return typeof e},e.exports.default=e.exports,e.exports.__esModule=!0):(e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.default=e.exports,e.exports.__esModule=!0),n(t)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},"./node_modules/@silverstripe/reactstrap-confirm/dist/Confirmation.js":function(e,t,n){"use strict";var r=n("./node_modules/@babel/runtime/helpers/interopRequireWildcard.js"),a=n("./node_modules/@babel/runtime/helpers/interopRequireDefault.js");t.__esModule=!0,t.default=void 0;var o=a(n("./node_modules/@babel/runtime/helpers/inheritsLoose.js")),i=r(n(2)),s=a(n(11)),l=n(17),d=function(e){function t(t){var n;return n=e.call(this,t)||this,n.state={isOpen:!0},n}return(0,o.default)(t,e),t.prototype.render=function(){var e=this,t=this.props,n=t.onConfirm,r=t.onCancel,a=t.title,o=t.body,s=t.confirmLabel,d=t.confirmColor,c=t.dismissLabel,u=t.showDismissButton,f=this.state.isOpen,p=function(){"function"==typeof r&&r(),e.setState({isOpen:!1})},h=function(){n(),e.setState({isOpen:!1})};return i.default.createElement(l.Modal,{isOpen:f,toggle:p},a&&i.default.createElement(l.ModalHeader,{toggle:p},a),i.default.createElement(l.ModalBody,null,o),i.default.createElement(l.ModalFooter,null,i.default.createElement(l.Button,{color:d,onClick:h},s),(u||!a)&&i.default.createElement(l.Button,{onClick:p},c||"Cancel")))},t}(i.Component);d.propTypes={onConfirm:s.default.func.isRequired,body:s.default.string.isRequired,onCancel:s.default.func,title:s.default.string,confirmLabel:s.default.string,confirmColor:s.default.string,dismissLabel:s.default.string},d.defaultProps={confirmLabel:"Confirm",confirmColor:"primary"};var c=d;t.default=c},"./node_modules/@silverstripe/reactstrap-confirm/dist/confirm.js":function(e,t,n){"use strict";var r=n("./node_modules/@babel/runtime/helpers/interopRequireDefault.js");t.__esModule=!0,t.default=void 0;var a=r(n("./node_modules/@babel/runtime/helpers/extends.js")),o=r(n(2)),i=r(n(5)),s=r(n("./node_modules/@silverstripe/reactstrap-confirm/dist/Confirmation.js")),l=function(e,t,n,r,l){void 0===t&&(t={}),void 0===n&&(n=document.body),void 0===r&&(r=350);var d=l||s.default,c=n.appendChild(document.createElement("div"));return new Promise(function(s){var l=function(e){return function(){s(e),setTimeout(function(){i.default.unmountComponentAtNode(c),setTimeout(function(){return n.removeChild(c)})},r)}};i.default.render(o.default.createElement(d,(0,a.default)({},t,{onConfirm:l(!0),onCancel:l(!1),body:e})),c)})},d=l;t.default=d},"./node_modules/@silverstripe/reactstrap-confirm/dist/index.js":function(e,t,n){"use strict";var r=n("./node_modules/@babel/runtime/helpers/interopRequireDefault.js");t.__esModule=!0,t.default=void 0;var a=r(n("./node_modules/@silverstripe/reactstrap-confirm/dist/confirm.js")),o=r(n("./node_modules/@silverstripe/reactstrap-confirm/dist/Confirmation.js"));t.Confirmation=o.default;var i=a.default;t.default=i},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=i18n},10:function(e,t){e.exports=GraphQLTag},11:function(e,t){e.exports=PropTypes},12:function(e,t){e.exports=Redux},13:function(e,t){e.exports=DeepFreezeStrict},14:function(e,t){e.exports=FieldHolder},15:function(e,t){e.exports=IsomorphicFetch},16:function(e,t){e.exports=ReactSelect},17:function(e,t){e.exports=Reactstrap},18:function(e,t){e.exports=ReduxForm},19:function(e,t){e.exports=SilverStripeComponent},2:function(e,t){e.exports=React},20:function(e,t){e.exports=classnames},21:function(e,t){e.exports=getFormState},3:function(e,t){e.exports=Injector},4:function(e,t){e.exports=ReactApollo},5:function(e,t){e.exports=ReactDom},6:function(e,t){e.exports=ReactRedux}});
|
!function(){"use strict";var e={274:function(e,t,n){var a=i(n(180)),o=i(n(521));function i(e){return e&&e.__esModule?e:{default:e}}window.document.addEventListener("DOMContentLoaded",(()=>{(0,o.default)(),(0,a.default)()}))},521:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=s(n(648)),o=s(n(93)),i=s(n(436)),r=s(n(149));function s(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{a.default.component.register("AnchorSelectorField",o.default),a.default.transform("pages-history",(e=>{e.component("HistoryViewer.pages-controller-cms-content",i.default,"PageHistoryViewer")})),a.default.transform("pages-history-revert",(e=>{e.component("HistoryViewerToolbar.VersionedAdmin.HistoryViewer.SiteTree.HistoryViewerVersionDetail",r.default,"PageRevertMutation")}))}},180:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(n(648)),o=n(827),i=r(n(572));function r(e){return e&&e.__esModule?e:{default:e}}t.default=()=>{a.default.reducer.register("cms",(0,o.combineReducers)({anchorSelector:i.default}))}},93:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.ConnectedAnchorSelectorField=t.Component=void 0;var a=C(n(754)),o=C(n(363)),i=C(n(875)),r=n(624),s=n(827),l=n(762),d=C(n(277)),u=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=_(t);if(n&&n.has(e))return n.get(e);var a={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var r=o?Object.getOwnPropertyDescriptor(e,i):null;r&&(r.get||r.set)?Object.defineProperty(a,i,r):a[i]=e[i]}a.default=e,n&&n.set(e,a);return a}(n(447)),c=C(n(892)),f=C(n(42)),p=C(n(453)),h=C(n(78)),m=C(n(720)),g=C(n(820)),v=C(n(86));function _(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_=function(e){return e?n:t})(e)}function C(e){return e&&e.__esModule?e:{default:e}}const b=()=>null;class w extends d.default{constructor(e){super(e),this.handleChange=this.handleChange.bind(this),this.handleLoadingError=this.handleLoadingError.bind(this)}componentDidMount(){this.ensurePagesLoaded()}componentDidUpdate(e){this.props.pageId!==e.pageId&&this.ensurePagesLoaded()}ensurePagesLoaded(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.props;if(e.loadingState===c.default.UPDATING||e.loadingState===c.default.SUCCESS||!e.pageId)return Promise.resolve();let t=[];e.loadingState===c.default.FIELD_ONLY&&(t=this.props.anchors),e.actions.anchorSelector.beginUpdating(e.pageId);const n=e.data.endpoint.replace(/:id/,e.pageId);return(0,i.default)(n,{credentials:"same-origin"}).then((e=>e.json())).then((n=>{const a=[...new Set([...n,...t])];return e.actions.anchorSelector.updated(e.pageId,a),a})).catch((t=>{e.actions.anchorSelector.updateFailed(e.pageId),this.handleLoadingError(t,e)}))}getDropdownOptions(){const e=this.props.anchors.map((e=>({value:e})));return this.props.value&&!this.props.anchors.find((e=>e===this.props.value))&&e.unshift({value:this.props.value}),e}handleChange(e){"function"==typeof this.props.onChange&&this.props.onChange(e?e.value:"")}handleLoadingError(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.props;if(t.onLoadingError===b)throw e;return t.onLoadingError({errors:[{value:e.message,type:"error"}]})}render(){const e=(0,g.default)("anchorselectorfield",this.props.extraClass),t=this.getDropdownOptions(),n=this.props.value||"",i=a.default._t("CMS.ANCHOR_SELECT_OR_TYPE","Select or enter anchor");return o.default.createElement(h.default,null,o.default.createElement(p.default,{isSearchable:!0,isClearable:!0,options:t,className:e,name:this.props.name,onChange:this.handleChange,value:{value:n},noOptionsMessage:()=>a.default._t("CMS.ANCHOR_NO_OPTIONS","No options"),placeholder:i,getOptionLabel:e=>{let{value:t}=e;return t},classNamePrefix:"anchorselectorfield"}))}}t.Component=w,w.propTypes={extraClass:v.default.string,id:v.default.string,name:v.default.string.isRequired,onChange:v.default.func,value:v.default.string,attributes:v.default.oneOfType([v.default.object,v.default.array]),pageId:v.default.number,anchors:v.default.array,loadingState:v.default.oneOf(Object.keys(c.default).map((e=>c.default[e]))),onLoadingError:v.default.func,data:v.default.shape({endpoint:v.default.string,targetFieldName:v.default.string})},w.defaultProps={value:"",extraClass:"",onLoadingError:b,attributes:{}};const S=(0,r.connect)((function(e,t){const n=(0,l.formValueSelector)(t.formid,m.default),a=t&&t.data&&t.data.targetFieldName||"PageID",o=Number(n(e,a)||0);let i=[];const r=o?e.cms.anchorSelector.pages.find((e=>e.id===o)):null;!r||r.loadingState!==c.default.SUCCESS&&r.loadingState!==c.default.DIRTY&&r.loadingState!==c.default.FIELD_ONLY||(i=r.anchors);let s=null;return s=r?r.loadingState:o?c.default.DIRTY:c.default.SUCCESS,{pageId:o,anchors:i,loadingState:s}}),(function(e){return{actions:{anchorSelector:(0,s.bindActionCreators)(u,e)}}}))(w);t.ConnectedAnchorSelectorField=S;var E=(0,f.default)(S);t.default=E},554:function(e,t,n){var a;((a=n(311))&&a.__esModule?a:{default:a}).default.entwine("ss",(function(e){e(".TreeDropdownField").entwine({OldValue:null}),e("#Form_AddForm_ParentID_Holder .treedropdownfield").entwine({onmatch(){this._super(),e(".cms-add-form").updateTypeList()}}),e(".cms-add-form .parent-mode :input").entwine({onclick:function(e){var t=this.closest("form").find("#Form_AddForm_ParentID_Holder .TreeDropdownField");"top"==this.val()?(t.setOldValue(t.getValue()),t.setValue(0)):(t.setValue(t.getOldValue()||0),t.setOldValue(null)),t.refresh(),t.trigger("change")}}),e(".cms-add-form").entwine({ParentCache:{},onadd:function(){var t=this;this.find("#Form_AddForm_ParentID_Holder .TreeDropdownField").on("change",(function(){t.updateTypeList()})),this.find(".SelectionGroup.parent-mode").on("change",(function(){t.updateTypeList()})),"top"==e(".cms-add-form .parent-mode :input").val()&&this.updateTypeList()},loadCachedChildren:function(e){var t=this.getParentCache();return void 0!==t[e]?t[e]:null},saveCachedChildren:function(e,t){var n=this.getParentCache();n[e]=t,this.setParentCache(n)},updateTypeList:function(){var t=this.data("hints"),n=this.find("#Form_AddForm_ParentID"),a=this.find("input[name=ParentModeField]:checked").val(),o=n.data("metadata"),i="child"===a?n.getValue():null,r=o?o.ClassName:null,s=r&&"child"===a&&i?r:"Root",l=void 0!==t[s]?t[s]:null,d=this,u=l&&void 0!==l.defaultChild?l.defaultChild:null,c=[];if(i){if(this.hasClass("loading"))return;return this.addClass("loading"),null!==(c=this.loadCachedChildren(i))?(this.updateSelectionFilter(c,u),void this.removeClass("loading")):(e.ajax({url:d.data("childfilter"),data:{ParentID:i},success:function(e){d.saveCachedChildren(i,e),d.updateSelectionFilter(e,u)},complete:function(){d.removeClass("loading")}}),!1)}c=l&&void 0!==l.disallowedChildren?l.disallowedChildren:[],this.updateSelectionFilter(c,u)},updateSelectionFilter:function(t,n){var a=this.find("#Form_AddForm_PageType div.radio.selected")[0],o=!1,i=null;if(this.find("#Form_AddForm_PageType div.radio").each((function(n,r){var s=e(this).find("input").val(),l=-1===e.inArray(s,t);r===a&&l&&(o=!0),e(this).setEnabled(l),l||e(this).setSelected(!1),i=(null===i||i)&&l})),o)var r=e(a).parents("li:first");else if(n)r=this.find("#Form_AddForm_PageType div.radio input[value="+n+"]").parents("li:first");else r=this.find("#Form_AddForm_PageType div.radio:not(.disabled):first");r.setSelected(!0),r.siblings().setSelected(!1),this.find("#Form_AddForm_PageType div.radio:not(.disabled)").length?this.find("button[name=action_doAdd]").removeAttr("disabled"):this.find("button[name=action_doAdd]").attr("disabled","disabled"),this.find(".message-restricted")[i?"hide":"show"]()}}),e(".cms-add-form #Form_AddForm_PageType div.radio").entwine({onclick:function(e){this.setSelected(!0)},setSelected:function(e){var t=this.find("input");e&&!t.is(":disabled")?(this.siblings().setSelected(!1),this.toggleClass("selected",!0),t.prop("checked",!0)):(this.toggleClass("selected",!1),t.prop("checked",!1))},setEnabled:function(t){e(this).toggleClass("disabled",!t),t?e(this).find("input").removeAttr("disabled"):e(this).find("input").attr("disabled","disabled").removeAttr("checked")}}),e(".cms-content-addpage-button").entwine({onclick:function(t){var n,a=e(".cms-tree"),o=e(".cms-list"),i=0;if(a.is(":visible")){var r=a.jstree("get_selected");i=r?e(r[0]).data("id"):null}else{var s=o.find('input[name="Page[GridState]"]').val();s&&(i=parseInt(JSON.parse(s).ParentID,10))}var l,d={selector:this.data("targetPanel"),pjax:this.data("pjax")};i?(n=this.data("extraParams")?this.data("extraParams"):"",l=e.path.addSearchParams(i18n.sprintf(this.data("urlAddpage"),i),n)):l=this.attr("href"),e(".cms-container").loadPanel(l,null,d),t.preventDefault(),this.blur()}})}))},649:function(e,t,n){var a=r(n(311)),o=r(n(754)),i=r(n(141));function r(e){return e&&e.__esModule?e:{default:e}}a.default.entwine("ss",(function(e){e(".cms-edit-form :input#Form_EditForm_ClassName").entwine({onchange:function(){alert(o.default._t("CMS.ALERTCLASSNAME"))}}),e(".cms-edit-form input[name=Title]").entwine({onmatch:function(){var t=this;t.data("OrigVal",t.val());var n=t.closest("form"),a=e("input:text[name=URLSegment]",n),o=e("input[name=LiveLink]",n);a.length>0&&(t._addActions(),this.on("change",(function(n){var i=t.data("OrigVal"),r=t.val();t.data("OrigVal",r),0===a.val().indexOf(a.data("defaultUrl"))&&""==o.val()?t.updateURLSegment(r):e(".update",t.parent()).show().parent(".form__field-holder").addClass("input-group"),t.updateRelatedFields(r,i),t.updateBreadcrumbLabel(r)}))),this._super()},onunmatch:function(){this._super()},updateRelatedFields:function(t,n){this.parents("form").find("input[name=MetaTitle], input[name=MenuTitle]").each((function(){var a=e(this);a.val()==n&&(a.val(t),a.updatedRelatedFields&&a.updatedRelatedFields())}))},updateURLSegment:function(t){var n=e("input:text[name=URLSegment]",this.closest("form")).closest(".field.urlsegment"),a=e(".update",this.parent());n.update(t),a.is(":visible")&&a.hide().parent(".form__field-holder").removeClass("input-group")},updateBreadcrumbLabel:function(t){e(".cms-edit-form input[name=ID]").val();var n=e("span.cms-panel-link.crumb");t&&""!=t&&n.text(t)},_addActions:function(){var t,n=this;(t=e("<button />",{class:"update btn btn-outline-secondary form__field-update-url",text:o.default._t("CMS.UpdateURL"),type:"button",click:function(e){e.preventDefault(),n.updateURLSegment(n.val())}})).insertAfter(n),t.hide()}}),e(".cms-edit-form .parentTypeSelector").entwine({onmatch:function(){var e=this;this.find(":input[name=ParentType]").on("click",(function(t){e._toggleSelection(t)})),this.find(".TreeDropdownField").on("change",(function(t){e._changeParentId(t)})),this._changeParentId(),this._toggleSelection(),this._super()},onunmatch:function(){this._super()},_toggleSelection:function(t){var n=this.find(":input[name=ParentType]:checked").val(),a=this.find("#Form_EditForm_ParentID_Holder");"root"==n?this.find(":input[name=ParentID]").val(0):this.find(":input[name=ParentID]").val(this.find("#Form_EditForm_ParentType_subpage").data("parentIdValue")),"root"!=n?a.slideDown(400,(function(){e(this).css("overflow","visible")})):a.slideUp()},_changeParentId:function(e){var t=this.find(":input[name=ParentID]").val();this.find("#Form_EditForm_ParentType_subpage").data("parentIdValue",t)}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_doRollback, .cms-edit-form .btn-toolbar #Form_EditForm_action_rollback").entwine({onclick:function(e){if(this.is(":disabled"))return e.preventDefault(),!1;const t=this.parents("form:first").find(":input[name=Version]").val(),n=t?o.default.sprintf(o.default._t("CMS.RollbackToVersion","Do you really want to roll back to version #%s of this page?"),t):o.default._t("CMS.ConfirmRestoreFromLive","Are you sure you want to revert draft to when the page was last published?");return confirm(n)?(this.parents("form:first").addClass("loading"),this._super(e)):(e.preventDefault(),!1)}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_archive:not(.homepage-warning)").entwine({onclick:function(e){var t;return t=this.parents("form:first").find("input[name=ArchiveWarningMessage]").val().replace(/\\n/g,"\n"),!!confirm(t)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_restore").entwine({onclick:function(e){var t,n=this.parents("form:first").find(":input[name=Version]").val(),a=this.data("toRoot");return t=o.default.sprintf(o.default._t(a?"CMS.RestoreToRoot":"CMS.Restore"),n),!!confirm(t)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form .btn-toolbar #Form_EditForm_action_unpublish:not(.homepage-warning)").entwine({onclick:function(e){var t,n=this.parents("form:first").find(":input[name=Version]").val();return t=o.default.sprintf(o.default._t("CMS.Unpublish"),n),!!confirm(t)&&(this.parents("form:first").addClass("loading"),this._super(e))}}),e(".cms-edit-form.changed").entwine({onmatch:function(t){this.find("button[data-text-alternate]").each((function(){const t=e(this),n=t.find(".btn__title"),a=t.data("textAlternate");a&&(t.data("textStandard",n.text()),n.text(a));const o=t.data("btnAlternate");o&&(t.data("btnStandard",t.attr("class")),t.attr("class",o),t.removeClass("btn-outline-secondary").addClass("btn-primary"));const i=t.data("btnAlternateAdd");i&&t.addClass(i);const r=t.data("btnAlternateRemove");r&&t.removeClass(r)})),this._super(t)},onunmatch:function(t){this.find("button[data-text-alternate]").each((function(){const t=e(this),n=t.find(".btn__title"),a=t.data("textStandard");a&&n.text(a);const o=t.data("btnStandard");o&&(t.attr("class",o),t.addClass("btn-outline-secondary").removeClass("btn-primary"));const i=t.data("btnAlternateAdd");i&&t.removeClass(i);const r=t.data("btnAlternateRemove");r&&t.addClass(r)})),this._super(t)}}),e(".cms-edit-form .btn-toolbar button[name=action_publish]").entwine({onbuttonafterrefreshalternate:function(){this.data("showingAlternate")?(this.addClass("btn-primary"),this.removeClass("btn-secondary")):(this.removeClass("btn-primary"),this.addClass("btn-secondary"))}}),e(".cms-edit-form .btn-toolbar button[name=action_save]").entwine({onbuttonafterrefreshalternate:function(){this.data("showingAlternate")?(this.addClass("btn-primary"),this.removeClass("btn-secondary")):(this.removeClass("btn-primary"),this.addClass("btn-secondary"))}}),e('.cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked').entwine({onmatch:function(){this.redraw(),this._super()},onunmatch:function(){this._super()},redraw:function(){var t=e(".cms-edit-form.CMSPageSettingsController #Form_EditForm_ParentID_Holder");"Form_EditForm_ParentType_root"==e(this).attr("id")?t.slideUp():t.slideDown()},onclick:function(){this.redraw()}}),"Form_EditForm_ParentType_root"==e('.cms-edit-form.CMSPageSettingsController input[name="ParentType"]:checked').attr("id")&&e(".cms-edit-form.CMSPageSettingsController #Form_EditForm_ParentID_Holder").hide();var t=!1;e(".cms-edit-form .btn-toolbar #Form_EditForm_action_unpublish.homepage-warning,.cms-edit-form .btn-toolbar #Form_EditForm_action_archive.homepage-warning,#Form_EditForm_URLSegment_Holder.homepage-warning .btn.update").entwine({onclick:async function(e){if(t)return this._super(e);e.stopPropagation();var n=o.default._t("CMS.RemoveHomePageWarningMessage","Warning: This page is the home page. By changing the URL segment visitors will not be able to view it.");return await(0,i.default)({title:o.default._t("CMS.RemoveHomePageWarningTitle","Remove your home page?"),message:n,confirmText:o.default._t("CMS.RemoveHomePageWarningLabel","Remove"),confirmColor:"danger"})&&(t=!0,this.trigger("click"),t=!1),!1}})}))},978:function(e,t,n){var a=s(n(311)),o=s(n(754)),i=s(n(141)),r=n(845);function s(e){return e&&e.__esModule?e:{default:e}}a.default.entwine("ss.tree",(function(e){e(".cms-tree").entwine({fromDocument:{"oncontext_show.vakata":function(e){this.adjustContextClass()}},adjustContextClass:function(){var t=e("#vakata-contextmenu").find("ul ul");t.each((function(n){var a="1",o=e(t[n]).find("li").length;o>20?a="3":o>10&&(a="2"),e(t[n]).addClass("vakata-col-"+a).removeClass("right"),e(t[n]).find("li").on("mouseenter",(function(t){e(this).parent("ul").removeClass("right")}))}))},showListViewFor:function(t){localStorage.setItem("ss.pages-view-type","listview");const n=this.closest(".cms-content-view").data("url-listviewroot"),a=e.path.addSearchParams(n,{ParentID:t}),o=e("base").attr("href")||"";window.location.assign((0,r.joinUrlPaths)(o,a))},getTreeConfig:function(){var t=this,n=this._super();this.getHints();return n.plugins.push("contextmenu"),n.contextmenu={items:function(n){var a={edit:{label:n.hasClass("edit-disabled")?o.default._t("CMS.EditPage","Edit page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"):o.default._t("CMS.ViewPage","View page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(o.default.sprintf(t.data("urlEditpage"),n.data("id")))}}};n.hasClass("nochildren")||(a.showaslist={label:o.default._t("CMS.ShowAsList"),action:function(e){t.showListViewFor(e.data("id"))}});n.data("pagetype");var i=n.data("id"),r=n.find(">a .item").data("allowedchildren"),s={},l=!1;return e.each(r,(function(n,a){l=!0,s["allowedchildren-"+a.ClassName]={label:'<span class="jstree-pageicon '+a.IconClass+'"></span>'+a.Title,_class:"class-"+a.ClassName.replace(/[^a-zA-Z0-9\-_:.]+/g,"_"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(o.default.sprintf(t.data("urlAddpage"),i,a.ClassName),t.data("extraParams")))}}})),l&&(a.addsubpage={label:o.default._t("CMS.AddSubPage","Add page under this page",100,"Used in the context menu when right-clicking on a page node in the CMS tree"),submenu:s}),n.hasClass("edit-disabled")||(a.duplicate={label:o.default._t("CMS.Duplicate"),submenu:[{label:o.default._t("CMS.ThisPageOnly"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(o.default.sprintf(t.data("urlDuplicate"),n.data("id")),t.data("extraParams")))}},{label:o.default._t("CMS.ThisPageAndSubpages"),action:function(n){e(".cms-container").entwine(".ss").loadPanel(e.path.addSearchParams(o.default.sprintf(t.data("urlDuplicatewithchildren"),n.data("id")),t.data("extraParams")))}}]}),a}},n},canMove:async function(e){if(!(e.rslt.o.find(".homepage").first().length>0))return!0;if(e.rslt.op.data("id")===e.rslt.np.data("id"))return!0;var t=o.default._t("CMS.RemoveHomePageWarningMessage","Warning: This page is the home page. By changing the URL segment visitors will not be able to view it.");return await(0,i.default)({title:o.default._t("CMS.RemoveHomePageWarningTitle","Remove your home page?"),message:t,confirmText:o.default._t("CMS.RemoveHomePageWarningLabel","Remove"),confirmColor:"danger"})}}),e(".cms-tree a.jstree-clicked").entwine({onmatch:function(){var e=this,t=e.parents(".cms-tree-view-sidebar");if(e.offset().top<0||e.offset().top>t.height()-e.height()){var n=e.parent();n.prev().length&&(n=n.prev()),n.get(0).scrollIntoView()}}}),e(".cms-tree-filtered .clear-filter").entwine({onclick:function(){window.location=location.protocol+"//"+location.host+location.pathname}}),e(".cms-tree .subtree-list-link").entwine({onclick:function(e){e.preventDefault(),this.closest(".cms-tree").showListViewFor(this.data("id"))}})}))},580:function(e,t,n){var a,o=(a=n(311))&&a.__esModule?a:{default:a},i=n(845);o.default.entwine("ss",(function(e){const t="treeview",n="listview";e(".cms-content-header-info").entwine({"from .cms-panel":{ontoggle:function(e){var t=this.closest(".cms-content").find(e.target);0!==t.length&&this.parent()[t.hasClass("collapsed")?"addClass":"removeClass"]("collapsed")}}}),e(".cms-panel-deferred.cms-content-view").entwine({onadd:function(){if(this.data("no-ajax"))return;var e=localStorage.getItem("ss.pages-view-type")||t;this.closest(".cms-content-tools").length>0&&(e=t);const a=this.data(`url-${e}`);let o=localStorage.getItem("ss.pages-view-filtered");"string"==typeof o&&"false"===o.toLowerCase()&&(o=!1),localStorage.setItem("ss.pages-view-filtered",!1),this.data("deferredNoCache",o||e===n),this.data("url",a+location.search),this._super()}}),e(".js-injector-boot .search-holder--cms").entwine({search(e){localStorage.setItem("ss.pages-view-filtered",!0),this._super(e)}}),e(".cms .page-view-link").entwine({onclick:function(t){t.preventDefault();const a=e(this).data("view"),o=this.closest(".cms-content-view"),r=o.data(`url-${a}`),s=0!==o.closest(".cms-content-tools").length;if(localStorage.setItem("ss.pages-view-type",a),s&&a===n){const t=e("base").attr("href")||"";window.location.assign((0,i.joinUrlPaths)(t,o.data("url-listviewroot")))}else o.data("url",r+location.search),o.redraw()}}),e(".cms .cms-clear-filter").entwine({onclick:function(t){t.preventDefault(),window.location=e(this).prop("href")}}),e(".cms-content-toolbar").entwine({onmatch:function(){var t=this;this._super(),e.each(this.find(".cms-actions-buttons-row .tool-button"),(function(){var n=e(this),a=n.data("toolid");n.hasClass("active");void 0!==a&&(n.data("active",!1).removeClass("active"),e("#"+a).hide(),t.bindActionButtonEvents(n))}))},onunmatch:function(){var t=this;this._super(),e.each(this.find(".cms-actions-buttons-row .tool-button"),(function(){var n=e(this);t.unbindActionButtonEvents(n)}))},bindActionButtonEvents:function(e){var t=this;e.on("click.cmsContentToolbar",(function(n){t.showHideTool(e)}))},unbindActionButtonEvents:function(e){e.off(".cmsContentToolbar")},showHideTool:function(t){var n=t.data("active"),a=t.data("toolid"),o=e("#"+a);e.each(this.find(".cms-actions-buttons-row .tool-button"),(function(){var t=e(this),n=e("#"+t.data("toolid"));t.data("toolid")!==a&&(n.hide(),t.data("active",!1))})),t[n?"removeClass":"addClass"]("active"),o[n?"hide":"show"](),t.data("active",!n)}})}))},907:function(e,t,n){var a;((a=n(311))&&a.__esModule?a:{default:a}).default.entwine("ss",(function(e){e("#Form_EditForm_RedirectionType input").entwine({onmatch:function(){e(this).attr("checked")&&this.toggle(),this._super()},onunmatch:function(){this._super()},onclick:function(){this.toggle()},toggle:function(){"Internal"==e(this).attr("value")?(e("#Form_EditForm_ExternalURL_Holder").hide(),e("#Form_EditForm_LinkToID_Holder").show(),e("#Form_EditForm_LinkToFile_Holder").hide()):"External"==e(this).attr("value")?(e("#Form_EditForm_ExternalURL_Holder").show(),e("#Form_EditForm_LinkToID_Holder").hide(),e("#Form_EditForm_LinkToFile_Holder").hide()):(e("#Form_EditForm_LinkToFile_Holder").show(),e("#Form_EditForm_ExternalURL_Holder").hide(),e("#Form_EditForm_LinkToID_Holder").hide())}})}))},806:function(e,t,n){var a;((a=n(311))&&a.__esModule?a:{default:a}).default.entwine("ss",(function(e){e(".field.urlsegment:not(.readonly)").entwine({MaxPreviewLength:55,Ellipsis:"...",onmatch:function(){this.find(":text").length&&this.toggleEdit(!1),this.redraw(),this._super()},redraw:function(){var e=this.find(":text"),t=decodeURI(e.data("prefix")+e.val()),n=t;t.length>this.getMaxPreviewLength()&&(n=this.getEllipsis()+t.substr(t.length-this.getMaxPreviewLength(),t.length)),this.find(".URL-link").attr("href",encodeURI(t+e.data("suffix"))).text(n)},toggleEdit:function(e){var t=this.find(":text");this.find(".preview-holder")[e?"hide":"show"](),this.find(".edit-holder")[e?"show":"hide"](),e&&(t.data("origval",t.val()),t.focus())},update:function(){var e=this,t=this.find(":text"),n=t.data("origval"),a=arguments[0],o=a&&""!==a?a:t.val();n!=o?(this.addClass("loading"),this.suggest(o,(function(n){t.val(decodeURIComponent(n.value)),e.toggleEdit(!1),e.removeClass("loading"),e.redraw()}))):(this.toggleEdit(!1),this.redraw())},cancel:function(){var e=this.find(":text");e.val(e.data("origval")),this.toggleEdit(!1)},suggest:function(t,n){var a=this,o=a.find(":text"),i=e.path.parseUrl(a.closest("form").attr("action")),r=i.hrefNoSearch+"/field/"+o.attr("name")+"/suggest/?value="+encodeURIComponent(t);i.search&&(r+="&"+i.search.replace(/^\?/,"")),e.ajax({url:r,success:function(e){n.apply(this,arguments)},error:function(e,t){e.statusText=e.responseText},complete:function(){a.removeClass("loading")}})}}),e(".field.urlsegment .text").entwine({onkeydown:function(e){13===e.keyCode&&(e.preventDefault(),this.closest(".field").update())}}),e(".field.urlsegment .edit").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").toggleEdit(!0)}}),e(".field.urlsegment .update").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").update()}}),e(".field.urlsegment .cancel").entwine({onclick:function(e){e.preventDefault(),this.closest(".field").cancel()}})}))},964:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default={ANCHORSELECTOR_CURRENT_FIELD:"ANCHORSELECTOR_CURRENT_FIELD",ANCHORSELECTOR_UPDATED:"ANCHORSELECTOR_UPDATED",ANCHORSELECTOR_UPDATING:"ANCHORSELECTOR_UPDATING",ANCHORSELECTOR_UPDATE_FAILED:"ANCHORSELECTOR_UPDATE_FAILED"}},447:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.beginUpdating=function(e){return{type:o.default.ANCHORSELECTOR_UPDATING,payload:{pageId:e}}},t.updateFailed=function(e){return{type:o.default.ANCHORSELECTOR_UPDATE_FAILED,payload:{pageId:e}}},t.updated=function(e,t){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return{type:o.default.ANCHORSELECTOR_UPDATED,payload:{pageId:e,anchors:t,cacheResult:n}}},t.updatedCurrentField=function(e,t,n){return{type:o.default.ANCHORSELECTOR_CURRENT_FIELD,payload:{pageId:e,anchors:t,fieldID:n}}};var a,o=(a=n(964))&&a.__esModule?a:{default:a}},572:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:s,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const n=(n,o)=>{const i=t.payload.pageId;return(0,a.default)({pages:[...e.pages.filter((e=>e.id!==i)),{id:i,loadingState:n,anchors:o}].sort(((e,t)=>e.id-t.id))})};switch(t.type){case o.default.ANCHORSELECTOR_UPDATING:return n(i.default.UPDATING,[]);case o.default.ANCHORSELECTOR_UPDATED:{const{anchors:e,cacheResult:a}=t.payload,{SUCCESS:o,DIRTY:r}=i.default;return n(a?o:r,e)}case o.default.ANCHORSELECTOR_CURRENT_FIELD:{const{anchors:e}=t.payload;return n(i.default.FIELD_ONLY,e)}case o.default.ANCHORSELECTOR_UPDATE_FAILED:return n(i.default.FAILED,[]);default:return e}};var a=r(n(752)),o=r(n(964)),i=r(n(892));function r(e){return e&&e.__esModule?e:{default:e}}const s=(0,a.default)({pages:[]})},892:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;t.default={SUCCESS:"SUCCESS",DIRTY:"DIRTY",FIELD_ONLY:"FIELD_ONLY",UPDATING:"UPDATING",FAILED:"FAILED"}},436:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.query=t.default=t.config=void 0;var a,o=n(732);const i=((a=n(306))&&a.__esModule?a:{default:a}).default`
|
||||||
|
query ReadHistoryViewerPage ($page_id: ID!, $limit: Int!, $offset: Int!) {
|
||||||
|
readOnePage(
|
||||||
|
versioning: {
|
||||||
|
mode: ALL_VERSIONS
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
id: { eq: $page_id }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
versions (limit: $limit, offset: $offset, sort: {
|
||||||
|
version: DESC
|
||||||
|
}) {
|
||||||
|
pageInfo {
|
||||||
|
totalCount
|
||||||
|
}
|
||||||
|
nodes {
|
||||||
|
version
|
||||||
|
absoluteLink
|
||||||
|
author {
|
||||||
|
firstName
|
||||||
|
surname
|
||||||
|
}
|
||||||
|
publisher {
|
||||||
|
firstName
|
||||||
|
surname
|
||||||
|
}
|
||||||
|
deleted
|
||||||
|
draft
|
||||||
|
published
|
||||||
|
liveVersion
|
||||||
|
latestDraftVersion
|
||||||
|
lastEdited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;t.query=i;const r={options(e){let{recordId:t,limit:n,page:a}=e;return{variables:{limit:n,offset:((a||1)-1)*n,page_id:t},fetchPolicy:"network-only"}},props(e){let{data:{error:t,refetch:n,readOnePage:a,loading:o},ownProps:{actions:i={versions:{}},limit:r,recordId:s}}=e;const l=a||null;return{loading:o||!l,versions:l,graphQLErrors:t&&t.graphQLErrors&&t.graphQLErrors.map((e=>e.message)),actions:{...i,versions:{...l,goToPage(e){n({offset:((e||1)-1)*r,limit:r,page_id:s})}}}}}};t.config=r;var s=(0,o.graphql)(i,r);t.default=s},149:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.mutation=t.default=t.config=void 0;var a,o=n(732);const i=((a=n(306))&&a.__esModule?a:{default:a}).default`
|
||||||
|
mutation rollbackPage($id:ID!, $toVersion:Int!) {
|
||||||
|
rollbackPage(
|
||||||
|
id: $id
|
||||||
|
toVersion: $toVersion
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;t.mutation=i;const r={props:e=>{let{mutate:t,ownProps:{actions:n}}=e;const a=(e,n)=>t({variables:{id:e,toVersion:n}});return{actions:{...n,rollbackPage:a,revertToVersion:a}}},options:{refetchQueries:["ReadHistoryViewerPage"]}};t.config=r;var s=(0,o.graphql)(i,r);t.default=s},112:function(e,t,n){function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o,i=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==a(e)&&"function"!=typeof e)return{default:e};var n=l(t);if(n&&n.has(e))return n.get(e);var o={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var r in e)if("default"!==r&&Object.prototype.hasOwnProperty.call(e,r)){var s=i?Object.getOwnPropertyDescriptor(e,r):null;s&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r]}o.default=e,n&&n.set(e,o);return o}(n(363)),r=(o=n(86))&&o.__esModule?o:{default:o},s=n(127);function l(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(l=function(e){return e?n:t})(e)}function d(){return d=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},d.apply(this,arguments)}var u=function(e){var t=e.onClose,n=e.message,a=e.title,o=e.confirmText,r=e.cancelText,l=e.confirmColor,u=e.cancelColor,c=e.className,f=e.buttonsComponent,p=e.size,h=e.bodyComponent,m=e.modalProps,g=i.default.createElement(i.Fragment,null,r&&i.default.createElement(s.Button,{color:u,onClick:function(){return t(!1)}},r)," ",i.default.createElement(s.Button,{color:l,onClick:function(){return t(!0)}},o));if(f){var v=f;g=i.default.createElement(v,{onClose:t})}var _=h;return i.default.createElement(s.Modal,d({size:p,isOpen:!0,toggle:function(){return t(!1)},className:"reactstrap-confirm ".concat(c)},m),a&&i.default.createElement(s.ModalHeader,{toggle:function(){return t(!1)}},a||null),i.default.createElement(s.ModalBody,null,h?i.default.createElement(_,null):n),i.default.createElement(s.ModalFooter,null,g))};u.defaultProps={message:"Are you sure?",title:"Warning!",confirmText:"Ok",cancelText:"Cancel",confirmColor:"primary",cancelColor:"",className:"",buttonsComponent:null,size:null,bodyComponent:null,modalProps:{}},u.propTypes={onClose:r.default.func.isRequired,message:r.default.node,title:r.default.node,confirmText:r.default.node,cancelText:r.default.node,confirmColor:r.default.string,cancelColor:r.default.string,className:r.default.string,size:r.default.string,buttonsComponent:r.default.func,bodyComponent:r.default.func,modalProps:r.default.object};var c=u;t.default=c},141:function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=r(n(363)),o=n(394),i=r(n(112));function r(e){return e&&e.__esModule?e:{default:e}}function s(){return s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},s.apply(this,arguments)}var l=function(e){return new Promise((function(t){var n=document.createElement("div");(0,o.render)(a.default.createElement(i.default,s({},e,{onClose:function(e){(0,o.unmountComponentAtNode)(n),n=null,t(e)}})),n)}))};t.default=l},732:function(e){e.exports=ApolloClientReactHoc},752:function(e){e.exports=DeepFreezeStrict},78:function(e){e.exports=EmotionCssCacheProvider},42:function(e){e.exports=FieldHolder},306:function(e){e.exports=GraphQLTag},648:function(e){e.exports=Injector},875:function(e){e.exports=IsomorphicFetch},86:function(e){e.exports=PropTypes},363:function(e){e.exports=React},394:function(e){e.exports=ReactDom},624:function(e){e.exports=ReactRedux},453:function(e){e.exports=ReactSelectCreatable},127:function(e){e.exports=Reactstrap},827:function(e){e.exports=Redux},762:function(e){e.exports=ReduxForm},277:function(e){e.exports=SilverStripeComponent},820:function(e){e.exports=classnames},720:function(e){e.exports=getFormState},754:function(e){e.exports=i18n},311:function(e){e.exports=jQuery},845:function(e){e.exports=ssUrlLib}},t={};function n(a){var o=t[a];if(void 0!==o)return o.exports;var i=t[a]={exports:{}};return e[a](i,i.exports,n),i.exports}n(554),n(649),n(580),n(978),n(907),n(806),n(274)}();
|
2
client/dist/styles/SilverStripeNavigator.css
vendored
2
client/dist/styles/SilverStripeNavigator.css
vendored
@ -1 +1 @@
|
|||||||
#SilverStripeNavigator{position:fixed;bottom:0;left:0;width:100%;border-top:2px solid #d4d0c8;background-color:#81858d;height:22px}#SilverStripeNavigator *{font-family:Arial,Helvetica,sans-serif;font-size:10px!important}#SilverStripeNavigator .holder{text-align:center;padding-top:4px;padding-left:3px;padding-right:6px;color:#fff;border-top:1px solid #555}#SilverStripeNavigator #logInStatus{float:right}#SilverStripeNavigator #switchView{float:left}#SilverStripeNavigator a{color:#fff;text-decoration:underline}#SilverStripeNavigator a,#SilverStripeNavigator a:hover{background-color:transparent}#SilverStripeNavigator .bottomTabs a{margin-right:8px;text-decoration:underline}#SilverStripeNavigator .bottomTabs a.current{font-weight:700;text-decoration:none}#SilverStripeNavigatorMessage{font-family:Lucida Grande,Verdana,Arial,"sans-serif";position:fixed;z-index:1000;right:20px;top:40px;padding:10px;border-color:#c99;color:#fff;background-color:#c00;border:1px solid #000}#SilverStripeNavigatorLinkPopup{display:none;position:absolute;top:-60px;height:50px;width:350px;left:200px;background-color:#fff;border:1px solid #000;z-index:100;color:#000;padding:5px}#SilverStripeNavigatorLinkPopup input{width:250px}#SilverStripeNavigatorLinkPopup a.close{color:blue;text-align:right;width:80%;border:none!important;cursor:pointer}
|
#SilverStripeNavigator{position:fixed;bottom:0;left:0;width:100%;border-top:2px solid #d4d0c8;background-color:#81858d;height:22px}#SilverStripeNavigator *{font-family:Arial,Helvetica,sans-serif;font-size:10px !important}#SilverStripeNavigator .holder{text-align:center;padding-top:4px;padding-left:3px;padding-right:6px;color:#fff;border-top:1px solid #555}#SilverStripeNavigator #logInStatus{float:right}#SilverStripeNavigator #switchView{float:left}#SilverStripeNavigator a{color:#fff;background-color:rgba(0,0,0,0);text-decoration:underline}#SilverStripeNavigator a:hover{background-color:rgba(0,0,0,0)}#SilverStripeNavigator .bottomTabs a{margin-right:8px;text-decoration:underline}#SilverStripeNavigator .bottomTabs a.current{font-weight:bold;text-decoration:none}#SilverStripeNavigatorMessage{font-family:"Lucida Grande",Verdana,Arial,"sans-serif";position:fixed;z-index:1000;right:20px;top:40px;padding:10px;border-color:#c99;color:#fff;background-color:#c00;border:1px solid #000}#SilverStripeNavigatorLinkPopup{display:none;position:absolute;top:-60px;height:50px;width:350px;left:200px;background-color:#fff;border:1px solid #000;z-index:100;color:#000;padding:5px}#SilverStripeNavigatorLinkPopup input{width:250px}#SilverStripeNavigatorLinkPopup a.close{color:blue;text-align:right;width:80%;border:none !important;cursor:pointer}
|
||||||
|
2
client/dist/styles/bundle.css
vendored
2
client/dist/styles/bundle.css
vendored
@ -1 +1 @@
|
|||||||
#cms-page-history-versions tr.loading{color:#999}#cms-page-history-versions tr.loading td:hover{cursor:none}#cms-page-history-versions td:hover{cursor:pointer}.CMSPageHistoryController{overflow:hidden}.CMSPageHistoryController ins{background-color:#dfd;padding:2px;text-decoration:none}.CMSPageHistoryController del{background-color:#fdd;padding:2px;color:#f44}.CMSPageHistoryController .htmleditorfield.readonly img{max-width:100%;height:auto}.CMSPageHistoryController .cms-content-tools.collapsed{overflow:hidden}#cms-content-listview .cms-tree-expand-trigger,#cms-content-treeview .cms-tree-expand-trigger{display:none}.cms-content-tools #cms-content-treeview .cms-content-toolbar{border-bottom:none;-webkit-box-shadow:none;box-shadow:none;margin-bottom:0}.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger{display:block;float:left;margin:0 0 2px}.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger span.ui-button-text{padding-right:8px}.cms-content-tools #cms-content-treeview .cms-tree .badge{display:none}.cms-content-tools #cms-content-treeview .cms-tree .jstree-clicked>.text>.badge,.cms-content-tools #cms-content-treeview .cms-tree a:hover>.text>.badge{display:inline-block}#cms-content-tools-CMSMain .search-form{right:0}.cms-list .cms-list__item-breadcrumbs{margin-left:21px;margin-bottom:0;font-size:.9em;word-break:break-word}.cms-content-toolbar .view-controls{margin-top:0}.cms-content-toolbar .view-controls .page-view-link{display:inline-block;margin-right:-5px}.cms-content-toolbar .view-controls.view-controls--listview .font-icon-list,.cms-content-toolbar .view-controls.view-controls--treeview .font-icon-tree{display:none}#pages-controller-cms-content,#pages-controller-cms-content+.cms-preview{width:50%}.field.urlsegment .input-group{width:auto;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.field.urlsegment.loading .form__field-label{background-image:url(data:image/gif;base64,R0lGODlhEAAQAPQAAP///wpakvj6+z9+qYivyg9dlC5yotfk7KvG2R9om3umxGubveXt8py80sjZ5k+IsFyRtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAkKAAAALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkECQoAAAAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkECQoAAAAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAkKAAAALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAkKAAAALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==);background-repeat:no-repeat;background-position:100%;padding-right:20px}.field.urlsegment .URL-link{padding-top:8px;display:inline-block}.field.urlsegment input.text{-webkit-box-flex:0;-webkit-flex:0 1 250px;flex:0 1 250px}.field.urlsegment .input-group-append{z-index:2}.field.urlsegment .input-group-append:last-of-type{z-index:1}.field.urlsegment .input-group-append .btn{margin-top:0;padding-top:.5385rem;padding-bottom:.5385rem}.field.urlsegment .help{margin-left:0}.field.urlsegment .edit-holder{display:none}.field.urlsegment .edit-holder .form__field-description{clear:both}.form__field-update-url{border-radius:0 3px 3px 0;margin-right:0;margin-left:-1px}
|
#cms-page-history-versions tr.loading{color:#999}#cms-page-history-versions tr.loading td:hover{cursor:none}#cms-page-history-versions td:hover{cursor:pointer}#cms-content-treeview .cms-tree-expand-trigger,#cms-content-listview .cms-tree-expand-trigger{display:none}.cms-content-tools #cms-content-treeview .cms-content-toolbar{border-bottom:none;box-shadow:none;margin-bottom:0}.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger{display:block;float:left;margin:0 0 2px 0}.cms-content-tools #cms-content-treeview .cms-tree-expand-trigger span.ui-button-text{padding-right:8px}.cms-content-tools #cms-content-treeview .cms-tree .badge{display:none}.cms-content-tools #cms-content-treeview .cms-tree a:hover>.text>.badge,.cms-content-tools #cms-content-treeview .cms-tree .jstree-clicked>.text>.badge{display:inline-block}#cms-content-tools-CMSMain .search-form{right:0}.cms-list .cms-list__item-breadcrumbs{margin-left:21px;margin-bottom:0;font-size:.9em;word-break:break-word}.cms-content-toolbar .view-controls{margin-top:0}.cms-content-toolbar .view-controls .page-view-link{display:inline-block;margin-right:-5px}.cms-content-toolbar .view-controls.view-controls--treeview .font-icon-tree,.cms-content-toolbar .view-controls.view-controls--listview .font-icon-list{display:none}#pages-controller-cms-content,#pages-controller-cms-content+.cms-preview{width:50%}.field.urlsegment .input-group{width:auto;flex-wrap:nowrap}.field.urlsegment.loading .form__field-label{background-image:url(data:image/gif;base64,R0lGODlhEAAQAPQAAP///wpakvj6+z9+qYivyg9dlC5yotfk7KvG2R9om3umxGubveXt8py80sjZ5k+IsFyRtgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFUCAgjmRpnqUwFGwhKoRgqq2YFMaRGjWA8AbZiIBbjQQ8AmmFUJEQhQGJhaKOrCksgEla+KIkYvC6SJKQOISoNSYdeIk1ayA8ExTyeR3F749CACH5BAkKAAAALAAAAAAQABAAAAVoICCKR9KMaCoaxeCoqEAkRX3AwMHWxQIIjJSAZWgUEgzBwCBAEQpMwIDwY1FHgwJCtOW2UDWYIDyqNVVkUbYr6CK+o2eUMKgWrqKhj0FrEM8jQQALPFA3MAc8CQSAMA5ZBjgqDQmHIyEAIfkECQoAAAAsAAAAABAAEAAABWAgII4j85Ao2hRIKgrEUBQJLaSHMe8zgQo6Q8sxS7RIhILhBkgumCTZsXkACBC+0cwF2GoLLoFXREDcDlkAojBICRaFLDCOQtQKjmsQSubtDFU/NXcDBHwkaw1cKQ8MiyEAIfkECQoAAAAsAAAAABAAEAAABVIgII5kaZ6AIJQCMRTFQKiDQx4GrBfGa4uCnAEhQuRgPwCBtwK+kCNFgjh6QlFYgGO7baJ2CxIioSDpwqNggWCGDVVGphly3BkOpXDrKfNm/4AhACH5BAkKAAAALAAAAAAQABAAAAVgICCOZGmeqEAMRTEQwskYbV0Yx7kYSIzQhtgoBxCKBDQCIOcoLBimRiFhSABYU5gIgW01pLUBYkRItAYAqrlhYiwKjiWAcDMWY8QjsCf4DewiBzQ2N1AmKlgvgCiMjSQhACH5BAkKAAAALAAAAAAQABAAAAVfICCOZGmeqEgUxUAIpkA0AMKyxkEiSZEIsJqhYAg+boUFSTAkiBiNHks3sg1ILAfBiS10gyqCg0UaFBCkwy3RYKiIYMAC+RAxiQgYsJdAjw5DN2gILzEEZgVcKYuMJiEAOwAAAAAAAAAAAA==);background-repeat:no-repeat;background-position:right center;padding-right:20px}.field.urlsegment .URL-link{padding-top:8px;display:inline-block}.field.urlsegment input.text{flex:0 1 250px}.field.urlsegment .input-group-append{z-index:2}.field.urlsegment .input-group-append:last-of-type{z-index:1}.field.urlsegment .input-group-append .btn{margin-top:0;padding-top:.5385rem;padding-bottom:.5385rem}.field.urlsegment .help{margin-left:0}.field.urlsegment .edit-holder{display:none}.field.urlsegment .edit-holder .form__field-description{clear:both}.form__field-update-url{border-radius:0 3px 3px 0;margin-right:0px;margin-left:-1px}
|
||||||
|
@ -2,7 +2,6 @@ require('../legacy/CMSMain.AddForm');
|
|||||||
require('../legacy/CMSMain.EditForm');
|
require('../legacy/CMSMain.EditForm');
|
||||||
require('../legacy/CMSMain');
|
require('../legacy/CMSMain');
|
||||||
require('../legacy/CMSMain.Tree');
|
require('../legacy/CMSMain.Tree');
|
||||||
require('../legacy/CMSPageHistoryController');
|
|
||||||
require('../legacy/RedirectorPage');
|
require('../legacy/RedirectorPage');
|
||||||
require('../legacy/SiteTreeURLSegmentField');
|
require('../legacy/SiteTreeURLSegmentField');
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ import SilverStripeComponent from 'lib/SilverStripeComponent';
|
|||||||
import * as anchorSelectorActions from 'state/anchorSelector/AnchorSelectorActions';
|
import * as anchorSelectorActions from 'state/anchorSelector/AnchorSelectorActions';
|
||||||
import anchorSelectorStates from 'state/anchorSelector/AnchorSelectorStates';
|
import anchorSelectorStates from 'state/anchorSelector/AnchorSelectorStates';
|
||||||
import fieldHolder from 'components/FieldHolder/FieldHolder';
|
import fieldHolder from 'components/FieldHolder/FieldHolder';
|
||||||
import { Creatable } from 'react-select';
|
import CreatableSelect from 'react-select/creatable';
|
||||||
|
import EmotionCssCacheProvider from 'containers/EmotionCssCacheProvider/EmotionCssCacheProvider';
|
||||||
import getFormState from 'lib/getFormState';
|
import getFormState from 'lib/getFormState';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
@ -117,26 +118,26 @@ class AnchorSelectorField extends SilverStripeComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const inputProps = {
|
|
||||||
id: this.props.id,
|
|
||||||
};
|
|
||||||
const className = classnames('anchorselectorfield', this.props.extraClass);
|
const className = classnames('anchorselectorfield', this.props.extraClass);
|
||||||
const options = this.getDropdownOptions();
|
const options = this.getDropdownOptions();
|
||||||
const value = this.props.value || '';
|
const rawValue = this.props.value || '';
|
||||||
const placeholder = i18n._t('CMS.ANCHOR_SELECT_OR_TYPE', 'Select or enter anchor');
|
const placeholder = i18n._t('CMS.ANCHOR_SELECT_OR_TYPE', 'Select or enter anchor');
|
||||||
return (
|
return (
|
||||||
<Creatable
|
<EmotionCssCacheProvider>
|
||||||
searchable
|
<CreatableSelect
|
||||||
options={options}
|
isSearchable
|
||||||
className={className}
|
isClearable
|
||||||
name={this.props.name}
|
options={options}
|
||||||
inputProps={inputProps}
|
className={className}
|
||||||
onChange={this.handleChange}
|
name={this.props.name}
|
||||||
onBlurResetsInput
|
onChange={this.handleChange}
|
||||||
value={value}
|
value={{ value: rawValue }}
|
||||||
placeholder={placeholder}
|
noOptionsMessage={() => i18n._t('CMS.ANCHOR_NO_OPTIONS', 'No options')}
|
||||||
labelKey="value"
|
placeholder={placeholder}
|
||||||
/>
|
getOptionLabel={({ value }) => value}
|
||||||
|
classNamePrefix="anchorselectorfield"
|
||||||
|
/>
|
||||||
|
</EmotionCssCacheProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import reactConfirm from "@silverstripe/reactstrap-confirm";
|
import reactConfirm from 'reactstrap-confirm';
|
||||||
|
|
||||||
$.entwine('ss', function($){
|
$.entwine('ss', function($){
|
||||||
/**
|
/**
|
||||||
@ -497,12 +497,13 @@ $.entwine('ss', function($){
|
|||||||
'By changing the URL segment visitors will not be able to view it.'
|
'By changing the URL segment visitors will not be able to view it.'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (await reactConfirm(message, {
|
if (await reactConfirm({
|
||||||
title: i18n._t(
|
title: i18n._t(
|
||||||
'CMS.RemoveHomePageWarningTitle',
|
'CMS.RemoveHomePageWarningTitle',
|
||||||
'Remove your home page?'
|
'Remove your home page?'
|
||||||
),
|
),
|
||||||
confirmLabel: i18n._t(
|
message,
|
||||||
|
confirmText: i18n._t(
|
||||||
'CMS.RemoveHomePageWarningLabel',
|
'CMS.RemoveHomePageWarningLabel',
|
||||||
'Remove'
|
'Remove'
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import reactConfirm from "@silverstripe/reactstrap-confirm";
|
import reactConfirm from 'reactstrap-confirm';
|
||||||
|
import { joinUrlPaths } from 'lib/urls';
|
||||||
|
|
||||||
$.entwine('ss.tree', function($) {
|
$.entwine('ss.tree', function($) {
|
||||||
$('.cms-tree').entwine({
|
$('.cms-tree').entwine({
|
||||||
@ -45,7 +46,7 @@ $.entwine('ss.tree', function($) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const baseUrl = $('base').attr('href') || ''; // Edge17 and IE11 require absolute paths
|
const baseUrl = $('base').attr('href') || ''; // Edge17 and IE11 require absolute paths
|
||||||
window.location.assign(baseUrl + urlWithParams);
|
window.location.assign(joinUrlPaths(baseUrl, urlWithParams));
|
||||||
},
|
},
|
||||||
|
|
||||||
getTreeConfig: function() {
|
getTreeConfig: function() {
|
||||||
@ -168,12 +169,13 @@ $.entwine('ss.tree', function($) {
|
|||||||
'By changing the URL segment visitors will not be able to view it.'
|
'By changing the URL segment visitors will not be able to view it.'
|
||||||
);
|
);
|
||||||
|
|
||||||
return await reactConfirm(message, {
|
return await reactConfirm({
|
||||||
title: i18n._t(
|
title: i18n._t(
|
||||||
'CMS.RemoveHomePageWarningTitle',
|
'CMS.RemoveHomePageWarningTitle',
|
||||||
'Remove your home page?'
|
'Remove your home page?'
|
||||||
),
|
),
|
||||||
confirmLabel: i18n._t(
|
message,
|
||||||
|
confirmText: i18n._t(
|
||||||
'CMS.RemoveHomePageWarningLabel',
|
'CMS.RemoveHomePageWarningLabel',
|
||||||
'Remove'
|
'Remove'
|
||||||
),
|
),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
import { joinUrlPaths } from 'lib/urls';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behaviour for the CMS Content Toolbar.
|
* Behaviour for the CMS Content Toolbar.
|
||||||
@ -81,7 +82,7 @@ $.entwine('ss', function ($) {
|
|||||||
localStorage.setItem('ss.pages-view-type', viewType);
|
localStorage.setItem('ss.pages-view-type', viewType);
|
||||||
if(isContentViewInSidebar && viewType === VIEW_TYPE_LIST) {
|
if(isContentViewInSidebar && viewType === VIEW_TYPE_LIST) {
|
||||||
const baseUrl = $('base').attr('href') || ''; // Edge17 and IE11 need absolute path
|
const baseUrl = $('base').attr('href') || ''; // Edge17 and IE11 need absolute path
|
||||||
window.location.assign(baseUrl + $contentView.data('url-listviewroot'));
|
window.location.assign(joinUrlPaths(baseUrl, $contentView.data('url-listviewroot')));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import i18n from 'i18n';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File: CMSPageHistoryController.js
|
|
||||||
*
|
|
||||||
* Handles related interactions between the version selection form on the
|
|
||||||
* left hand side of the panel and the version displaying on the right
|
|
||||||
* hand side.
|
|
||||||
*/
|
|
||||||
$.entwine('ss', ($) => { // eslint-disable-line no-shadow
|
|
||||||
/**
|
|
||||||
* Class: #Form_VersionsForm
|
|
||||||
*
|
|
||||||
* The left hand side version selection form is the main interface for
|
|
||||||
* users to select a version to view, or to compare two versions
|
|
||||||
*/
|
|
||||||
$('#Form_VersionsForm').entwine({
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
onmatch() {
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
onunmatch() {
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Function: submit.
|
|
||||||
*
|
|
||||||
* Submits either the compare versions form or the view single form
|
|
||||||
* display based on whether we have two or 1 option selected
|
|
||||||
*
|
|
||||||
* Todo:
|
|
||||||
* Handle coupling to admin url
|
|
||||||
*/
|
|
||||||
onsubmit(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const id = this.find(':input[name=ID]').val();
|
|
||||||
|
|
||||||
if (!id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = null;
|
|
||||||
let to = null;
|
|
||||||
let from = null;
|
|
||||||
|
|
||||||
const compare = (this.find(':input[name=CompareMode]').is(':checked'));
|
|
||||||
const selected = this.find('table input[type=checkbox]').filter(':checked');
|
|
||||||
|
|
||||||
if (compare) {
|
|
||||||
if (selected.length !== 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
to = selected.eq(0).val();
|
|
||||||
from = selected.eq(1).val();
|
|
||||||
url = i18n.sprintf(this.data('linkTmplCompare'), id, from, to);
|
|
||||||
} else {
|
|
||||||
to = selected.eq(0).val();
|
|
||||||
url = i18n.sprintf(this.data('linkTmplShow'), id, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.cms-container').loadPanel(url, '', { pjax: 'CurrentForm' });
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: :input[name=ShowUnpublished]
|
|
||||||
*
|
|
||||||
* Used for toggling whether to show or hide unpublished versions.
|
|
||||||
*/
|
|
||||||
$('#Form_VersionsForm input[name=ShowUnpublished]').entwine({
|
|
||||||
onmatch() {
|
|
||||||
this.toggle();
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
onunmatch() {
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Event: :input[name=ShowUnpublished] change
|
|
||||||
*
|
|
||||||
* Changing the show unpublished checkbox toggles whether to show
|
|
||||||
* or hide the unpublished versions. Because those rows may be being
|
|
||||||
* compared this also ensures those rows are unselected.
|
|
||||||
*/
|
|
||||||
onchange() {
|
|
||||||
this.toggle();
|
|
||||||
},
|
|
||||||
toggle() {
|
|
||||||
const self = $(this);
|
|
||||||
const unpublished = self.parents('form').find('tr[data-published=false]');
|
|
||||||
|
|
||||||
if (self.attr('checked')) {
|
|
||||||
unpublished
|
|
||||||
.removeClass('ui-helper-hidden')
|
|
||||||
.show();
|
|
||||||
} else {
|
|
||||||
unpublished
|
|
||||||
.addClass('ui-helper-hidden')
|
|
||||||
.hide()
|
|
||||||
._unselect();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class: #Form_VersionsForm tr
|
|
||||||
*
|
|
||||||
* An individual row in the versions form. Selecting the row updates
|
|
||||||
* the edit form depending on whether we're showing individual version
|
|
||||||
* information or displaying comparsion.
|
|
||||||
*/
|
|
||||||
$('#Form_VersionsForm tbody tr').entwine({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function: onclick
|
|
||||||
*
|
|
||||||
* Selects or deselects the row (if in compare mode). Will trigger
|
|
||||||
* an update of the edit form if either selected (in single mode)
|
|
||||||
* or if this is the second row selected (in compare mode)
|
|
||||||
*/
|
|
||||||
onclick() {
|
|
||||||
// compare mode
|
|
||||||
const compare = this.parents('form').find(':input[name=CompareMode]').attr('checked');
|
|
||||||
const selected = this.siblings('.active');
|
|
||||||
|
|
||||||
if (compare && this.hasClass('active')) {
|
|
||||||
this._unselect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compare) {
|
|
||||||
// check if we have already selected more than two.
|
|
||||||
if (selected.length > 1) {
|
|
||||||
// eslint-disable-next-line no-alert
|
|
||||||
alert(i18n._t('CMS.ONLYSELECTTWO', 'You can only compare two versions at this time.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._select();
|
|
||||||
|
|
||||||
// if this is the second selected then we can compare.
|
|
||||||
if (selected.length === 1) {
|
|
||||||
this.parents('form').submit();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._select();
|
|
||||||
selected._unselect();
|
|
||||||
this.parents('form').submit();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function: _unselect()
|
|
||||||
*
|
|
||||||
* Unselects the row from the form selection.
|
|
||||||
*
|
|
||||||
* Using regular js to update the class rather than this.removeClass('active')
|
|
||||||
* because the latter causes the browser to continuously call
|
|
||||||
* element.compareDocumentPosition, causing the browser to hang for long
|
|
||||||
* periods of time, especially on pages with lots of versions (e.g. 100+)
|
|
||||||
*/
|
|
||||||
_unselect() {
|
|
||||||
this.get(0).classList.remove('active');
|
|
||||||
this.find(':input[type=checkbox][checked]').attr('checked', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function: _select()
|
|
||||||
*
|
|
||||||
* Selects the currently matched row in the form selection
|
|
||||||
*/
|
|
||||||
_select() {
|
|
||||||
this.addClass('active');
|
|
||||||
this.find(':input[type=checkbox]').attr('checked', true);
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
@ -2,8 +2,8 @@
|
|||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar';
|
import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { ApolloProvider } from 'react-apollo';
|
import { ApolloProvider } from '@apollo/client';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import jQuery from 'jquery';
|
import jQuery from 'jquery';
|
||||||
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
|
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
|
||||||
@ -19,7 +19,7 @@ TinyMCEActionRegistrar
|
|||||||
'sslink',
|
'sslink',
|
||||||
{
|
{
|
||||||
text: i18n._t('CMS.LINKLABEL_ANCHOR', 'Anchor on a page'),
|
text: i18n._t('CMS.LINKLABEL_ANCHOR', 'Anchor on a page'),
|
||||||
onclick: (activeEditor) => activeEditor.execCommand(commandName),
|
onAction: (activeEditor) => activeEditor.execCommand(commandName),
|
||||||
priority: 60,
|
priority: 60,
|
||||||
},
|
},
|
||||||
editorIdentifier,
|
editorIdentifier,
|
||||||
@ -32,8 +32,8 @@ const plugin = {
|
|||||||
const field = jQuery(`#${editor.id}`).entwine('ss');
|
const field = jQuery(`#${editor.id}`).entwine('ss');
|
||||||
// Get the anchors in the current field and save them as props for AnchorSelectorField
|
// Get the anchors in the current field and save them as props for AnchorSelectorField
|
||||||
const currentPageID = Number(jQuery('#Form_EditForm_ID').val() || 0);
|
const currentPageID = Number(jQuery('#Form_EditForm_ID').val() || 0);
|
||||||
const validTargets = editor
|
const validTargets = jQuery(editor.getBody())
|
||||||
.$('[id],[name]', editor.getBody())
|
.find('[id],[name]')
|
||||||
.toArray()
|
.toArray()
|
||||||
.map((element) => element.id || element.name);
|
.map((element) => element.id || element.name);
|
||||||
ss.store.dispatch(updatedCurrentField(currentPageID, validTargets, editor.id));
|
ss.store.dispatch(updatedCurrentField(currentPageID, validTargets, editor.id));
|
||||||
@ -68,20 +68,28 @@ jQuery.entwine('ss', ($) => {
|
|||||||
* Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions
|
* Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions
|
||||||
*/
|
*/
|
||||||
$(`#${modalId}`).entwine({
|
$(`#${modalId}`).entwine({
|
||||||
|
ReactRoot: null,
|
||||||
|
|
||||||
renderModal(isOpen) {
|
renderModal(isOpen) {
|
||||||
const store = ss.store;
|
const store = ss.store;
|
||||||
const client = ss.apolloClient;
|
const client = ss.apolloClient;
|
||||||
const handleHide = () => this.close();
|
const handleHide = () => this.close();
|
||||||
const handleInsert = (...args) => this.handleInsert(...args);
|
const handleInsert = (...args) => this.handleInsert(...args);
|
||||||
const attrs = this.getOriginalAttributes();
|
const attrs = this.getOriginalAttributes();
|
||||||
const selection = tinymce.activeEditor.selection;
|
const editor = this.getElement().getEditor();
|
||||||
const selectionContent = selection.getContent() || '';
|
const selection = editor.getInstance().selection;
|
||||||
|
const selectionContent = editor.getSelection();
|
||||||
const tagName = selection.getNode().tagName;
|
const tagName = selection.getNode().tagName;
|
||||||
const requireLinkText = tagName !== 'A' && selectionContent.trim() === '';
|
const requireLinkText = tagName !== 'A' && selectionContent.trim() === '';
|
||||||
const currentPageID = Number($('#Form_EditForm_ID').val() || 0);
|
const currentPageID = Number($('#Form_EditForm_ID').val() || 0);
|
||||||
|
|
||||||
// create/update the react component
|
// create/update the react component
|
||||||
ReactDOM.render(
|
let root = this.getReactRoot();
|
||||||
|
if (!root) {
|
||||||
|
root = createRoot(this[0]);
|
||||||
|
this.setReactRoot(root);
|
||||||
|
}
|
||||||
|
root.render(
|
||||||
<ApolloProvider client={client}>
|
<ApolloProvider client={client}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<InsertLinkInternalModal
|
<InsertLinkInternalModal
|
||||||
@ -97,8 +105,7 @@ jQuery.entwine('ss', ($) => {
|
|||||||
currentPageID={currentPageID}
|
currentPageID={currentPageID}
|
||||||
/>
|
/>
|
||||||
</Provider>
|
</Provider>
|
||||||
</ApolloProvider>,
|
</ApolloProvider>
|
||||||
this[0]
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar';
|
import TinyMCEActionRegistrar from 'lib/TinyMCEActionRegistrar';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { ApolloProvider } from 'react-apollo';
|
import { ApolloProvider } from '@apollo/client';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import jQuery from 'jquery';
|
import jQuery from 'jquery';
|
||||||
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
|
import ShortcodeSerialiser from 'lib/ShortcodeSerialiser';
|
||||||
@ -18,7 +18,7 @@ TinyMCEActionRegistrar
|
|||||||
'sslink',
|
'sslink',
|
||||||
{
|
{
|
||||||
text: i18n._t('CMS.LINKLABEL_PAGE', 'Page on this site'),
|
text: i18n._t('CMS.LINKLABEL_PAGE', 'Page on this site'),
|
||||||
onclick: (activeEditor) => activeEditor.execCommand(commandName),
|
onAction: (activeEditor) => activeEditor.execCommand(commandName),
|
||||||
priority: 90,
|
priority: 90,
|
||||||
},
|
},
|
||||||
editorIdentifier,
|
editorIdentifier,
|
||||||
@ -60,6 +60,8 @@ jQuery.entwine('ss', ($) => {
|
|||||||
* Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions
|
* Assumes that $('.insert-link__dialog-wrapper').entwine({}); is defined for shared functions
|
||||||
*/
|
*/
|
||||||
$(`#${modalId}`).entwine({
|
$(`#${modalId}`).entwine({
|
||||||
|
ReactRoot: null,
|
||||||
|
|
||||||
renderModal(isOpen) {
|
renderModal(isOpen) {
|
||||||
const store = ss.store;
|
const store = ss.store;
|
||||||
const client = ss.apolloClient;
|
const client = ss.apolloClient;
|
||||||
@ -69,7 +71,12 @@ jQuery.entwine('ss', ($) => {
|
|||||||
const requireLinkText = this.getRequireLinkText();
|
const requireLinkText = this.getRequireLinkText();
|
||||||
|
|
||||||
// create/update the react component
|
// create/update the react component
|
||||||
ReactDOM.render(
|
let root = this.getReactRoot();
|
||||||
|
if (!root) {
|
||||||
|
root = createRoot(this[0]);
|
||||||
|
this.setReactRoot(root);
|
||||||
|
}
|
||||||
|
root.render(
|
||||||
<ApolloProvider client={client}>
|
<ApolloProvider client={client}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<InsertLinkInternalModal
|
<InsertLinkInternalModal
|
||||||
@ -84,8 +91,7 @@ jQuery.entwine('ss', ($) => {
|
|||||||
requireLinkText={requireLinkText}
|
requireLinkText={requireLinkText}
|
||||||
/>
|
/>
|
||||||
</Provider>
|
</Provider>
|
||||||
</ApolloProvider>,
|
</ApolloProvider>
|
||||||
this[0]
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -95,8 +101,10 @@ jQuery.entwine('ss', ($) => {
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
getRequireLinkText() {
|
getRequireLinkText() {
|
||||||
const selection = this.getElement().getEditor().getInstance().selection;
|
const editor = this.getElement().getEditor();
|
||||||
const selectionContent = selection.getContent() || '';
|
const selection = editor.getInstance().selection;
|
||||||
|
const selectionContent = editor.getSelection();
|
||||||
|
|
||||||
const tagName = selection.getNode().tagName;
|
const tagName = selection.getNode().tagName;
|
||||||
const requireLinkText = tagName !== 'A' && selectionContent.trim() === '';
|
const requireLinkText = tagName !== 'A' && selectionContent.trim() === '';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { graphql } from 'react-apollo';
|
import { graphql } from '@apollo/client/react/hoc';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
// GraphQL query for retrieving the version history of a specific page. The
|
// GraphQL query for retrieving the version history of a specific page. The
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { graphql } from 'react-apollo';
|
import { graphql } from '@apollo/client/react/hoc';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
const mutation = gql`
|
const mutation = gql`
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { graphql } from 'react-apollo';
|
import { graphql } from '@apollo/client/react/hoc';
|
||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
const mutation = gql`
|
const mutation = gql`
|
||||||
|
@ -30,31 +30,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.CMSPageHistoryController {
|
|
||||||
overflow: hidden; // Fixes weird bug for double scroll in history area on browser resize
|
|
||||||
|
|
||||||
ins {
|
|
||||||
background-color: #DFD;
|
|
||||||
padding: 2px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
del {
|
|
||||||
background-color: #FDD;
|
|
||||||
padding: 2px;
|
|
||||||
color: darken(#FDD, 30%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.htmleditorfield.readonly img {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cms-content-tools.collapsed {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** --------------------------------------------
|
/** --------------------------------------------
|
||||||
* Tree View (collapsed for sidebar)
|
* Tree View (collapsed for sidebar)
|
||||||
* -------------------------------------------- */
|
* -------------------------------------------- */
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\CMS\BatchActions;
|
|||||||
|
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
use SilverStripe\Admin\CMSBatchAction;
|
use SilverStripe\Admin\CMSBatchAction;
|
||||||
|
use SilverStripe\Control\HTTPResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete items batch action.
|
* Delete items batch action.
|
||||||
@ -15,7 +16,7 @@ class CMSBatchAction_Archive extends CMSBatchAction
|
|||||||
return _t(__CLASS__ . '.TITLE', 'Unpublish and archive');
|
return _t(__CLASS__ . '.TITLE', 'Unpublish and archive');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(SS_List $pages)
|
public function run(SS_List $pages): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->batchaction(
|
return $this->batchaction(
|
||||||
$pages,
|
$pages,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace SilverStripe\CMS\BatchActions;
|
namespace SilverStripe\CMS\BatchActions;
|
||||||
|
|
||||||
use SilverStripe\Admin\CMSBatchAction;
|
use SilverStripe\Admin\CMSBatchAction;
|
||||||
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +16,7 @@ class CMSBatchAction_Publish extends CMSBatchAction
|
|||||||
return _t(__CLASS__ . '.PUBLISH_PAGES', 'Publish');
|
return _t(__CLASS__ . '.PUBLISH_PAGES', 'Publish');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(SS_List $pages)
|
public function run(SS_List $pages): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->batchaction(
|
return $this->batchaction(
|
||||||
$pages,
|
$pages,
|
||||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\CMS\BatchActions;
|
|||||||
|
|
||||||
use SilverStripe\Admin\CMSBatchAction;
|
use SilverStripe\Admin\CMSBatchAction;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\ORM\ArrayList;
|
use SilverStripe\ORM\ArrayList;
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
@ -20,7 +21,7 @@ class CMSBatchAction_Restore extends CMSBatchAction
|
|||||||
return _t(__CLASS__ . '.RESTORE', 'Restore');
|
return _t(__CLASS__ . '.RESTORE', 'Restore');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(SS_List $pages)
|
public function run(SS_List $pages): HTTPResponse
|
||||||
{
|
{
|
||||||
// Sort pages by depth
|
// Sort pages by depth
|
||||||
$pageArray = $pages->toArray();
|
$pageArray = $pages->toArray();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace SilverStripe\CMS\BatchActions;
|
namespace SilverStripe\CMS\BatchActions;
|
||||||
|
|
||||||
use SilverStripe\Admin\CMSBatchAction;
|
use SilverStripe\Admin\CMSBatchAction;
|
||||||
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +16,7 @@ class CMSBatchAction_Unpublish extends CMSBatchAction
|
|||||||
return _t(__CLASS__ . '.UNPUBLISH_PAGES', 'Unpublish');
|
return _t(__CLASS__ . '.UNPUBLISH_PAGES', 'Unpublish');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(SS_List $pages)
|
public function run(SS_List $pages): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->batchaction(
|
return $this->batchaction(
|
||||||
$pages,
|
$pages,
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Admin\AdminRootController;
|
use SilverStripe\Admin\AdminRootController;
|
||||||
use SilverStripe\Admin\CMSBatchActionHandler;
|
use SilverStripe\Admin\CMSBatchActionHandler;
|
||||||
use SilverStripe\Admin\LeftAndMain;
|
use SilverStripe\Admin\LeftAndMain;
|
||||||
use SilverStripe\Admin\LeftAndMainFormRequestHandler;
|
use SilverStripe\Admin\LeftAndMainFormRequestHandler;
|
||||||
|
use SilverStripe\Admin\Navigator\SilverStripeNavigator;
|
||||||
use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive;
|
use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive;
|
||||||
use SilverStripe\CMS\BatchActions\CMSBatchAction_Publish;
|
use SilverStripe\CMS\BatchActions\CMSBatchAction_Publish;
|
||||||
use SilverStripe\CMS\BatchActions\CMSBatchAction_Restore;
|
use SilverStripe\CMS\BatchActions\CMSBatchAction_Restore;
|
||||||
@ -23,6 +23,7 @@ use SilverStripe\Control\Director;
|
|||||||
use SilverStripe\Control\HTTPRequest;
|
use SilverStripe\Control\HTTPRequest;
|
||||||
use SilverStripe\Control\HTTPResponse;
|
use SilverStripe\Control\HTTPResponse;
|
||||||
use SilverStripe\Control\HTTPResponse_Exception;
|
use SilverStripe\Control\HTTPResponse_Exception;
|
||||||
|
use SilverStripe\Control\PjaxResponseNegotiator;
|
||||||
use SilverStripe\Core\Cache\MemberCacheFlusher;
|
use SilverStripe\Core\Cache\MemberCacheFlusher;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
@ -69,10 +70,9 @@ use SilverStripe\SiteConfig\SiteConfig;
|
|||||||
use SilverStripe\Versioned\ChangeSet;
|
use SilverStripe\Versioned\ChangeSet;
|
||||||
use SilverStripe\Versioned\ChangeSetItem;
|
use SilverStripe\Versioned\ChangeSetItem;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
|
use SilverStripe\VersionedAdmin\Controllers\CMSPageHistoryViewerController;
|
||||||
use SilverStripe\View\ArrayData;
|
use SilverStripe\View\ArrayData;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use Translatable;
|
|
||||||
use SilverStripe\VersionedAdmin\Controllers\CMSPageHistoryViewerController;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main "content" area of the CMS.
|
* The main "content" area of the CMS.
|
||||||
@ -107,12 +107,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
private static $tree_class = SiteTree::class;
|
private static $tree_class = SiteTree::class;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 1.13.0 Do not use this options.
|
|
||||||
* @config
|
|
||||||
*/
|
|
||||||
private static $subitem_class = Member::class;
|
|
||||||
|
|
||||||
private static $session_namespace = self::class;
|
private static $session_namespace = self::class;
|
||||||
|
|
||||||
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
||||||
@ -188,11 +182,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
protected function init()
|
protected function init()
|
||||||
{
|
{
|
||||||
// set reading lang
|
|
||||||
if (SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) {
|
|
||||||
Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages(SiteTree::class) ?? []));
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::init();
|
parent::init();
|
||||||
|
|
||||||
Requirements::javascript('silverstripe/cms: client/dist/js/bundle.js');
|
Requirements::javascript('silverstripe/cms: client/dist/js/bundle.js');
|
||||||
@ -200,7 +189,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
Requirements::css('silverstripe/cms: client/dist/styles/bundle.css');
|
Requirements::css('silverstripe/cms: client/dist/styles/bundle.css');
|
||||||
Requirements::customCSS($this->generatePageIconsCss(), self::PAGE_ICONS_ID);
|
Requirements::customCSS($this->generatePageIconsCss(), self::PAGE_ICONS_ID);
|
||||||
|
|
||||||
Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false, true);
|
Requirements::add_i18n_javascript('silverstripe/cms: client/lang', false);
|
||||||
|
|
||||||
CMSBatchActionHandler::register('restore', CMSBatchAction_Restore::class);
|
CMSBatchActionHandler::register('restore', CMSBatchAction_Restore::class);
|
||||||
CMSBatchActionHandler::register('archive', CMSBatchAction_Archive::class);
|
CMSBatchActionHandler::register('archive', CMSBatchAction_Archive::class);
|
||||||
@ -208,7 +197,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
CMSBatchActionHandler::register('publish', CMSBatchAction_Publish::class);
|
CMSBatchActionHandler::register('publish', CMSBatchAction_Publish::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index($request)
|
public function index(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
// In case we're not showing a specific record, explicitly remove any session state,
|
// In case we're not showing a specific record, explicitly remove any session state,
|
||||||
// to avoid it being highlighted in the tree, and causing an edit form to show.
|
// to avoid it being highlighted in the tree, and causing an edit form to show.
|
||||||
@ -219,7 +208,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return parent::index($request);
|
return parent::index($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getResponseNegotiator()
|
public function getResponseNegotiator(): PjaxResponseNegotiator
|
||||||
{
|
{
|
||||||
$negotiator = parent::getResponseNegotiator();
|
$negotiator = parent::getResponseNegotiator();
|
||||||
|
|
||||||
@ -414,10 +403,13 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
public function LinkPageHistory()
|
public function LinkPageHistory()
|
||||||
{
|
{
|
||||||
if ($id = $this->currentPageID()) {
|
$controller = Injector::inst()->get(CMSPageHistoryViewerController::class);
|
||||||
return $this->LinkWithSearch(
|
if (($id = $this->currentPageID()) && $controller) {
|
||||||
Controller::join_links(CMSPageHistoryViewerController::singleton()->Link('show'), $id)
|
if ($controller) {
|
||||||
);
|
return $this->LinkWithSearch(
|
||||||
|
Controller::join_links($controller->Link('show'), $id)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -664,11 +656,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Get a subtree underneath the request param 'ID'.
|
* Get a subtree underneath the request param 'ID'.
|
||||||
* If ID = 0, then get the whole tree.
|
* If ID = 0, then get the whole tree.
|
||||||
*
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function getsubtree($request)
|
public function getsubtree(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
$html = $this->getSiteTreeFor(
|
$html = $this->getSiteTreeFor(
|
||||||
$this->config()->get('tree_class'),
|
$this->config()->get('tree_class'),
|
||||||
@ -683,7 +672,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$html = preg_replace('/^[\s\t\r\n]*<ul[^>]*>/', '', $html ?? '');
|
$html = preg_replace('/^[\s\t\r\n]*<ul[^>]*>/', '', $html ?? '');
|
||||||
$html = preg_replace('/<\/ul[^>]*>[\s\t\r\n]*$/', '', $html ?? '');
|
$html = preg_replace('/<\/ul[^>]*>[\s\t\r\n]*$/', '', $html ?? '');
|
||||||
|
|
||||||
return $html;
|
return $this->getResponse()->setBody($html);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -691,11 +680,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
* Similar to {@link getsubtree()}, but doesn't enforce loading
|
* Similar to {@link getsubtree()}, but doesn't enforce loading
|
||||||
* all children with the node. Useful to refresh views after
|
* all children with the node. Useful to refresh views after
|
||||||
* state modifications, e.g. saving a form.
|
* state modifications, e.g. saving a form.
|
||||||
*
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
*/
|
||||||
public function updatetreenodes($request)
|
public function updatetreenodes(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
$data = [];
|
$data = [];
|
||||||
$ids = explode(',', $request->getVar('ids') ?? '');
|
$ids = explode(',', $request->getVar('ids') ?? '');
|
||||||
@ -763,17 +749,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
* - 'SiblingIDs': Array of all sibling nodes to the moved node (incl. the node itself).
|
* - 'SiblingIDs': Array of all sibling nodes to the moved node (incl. the node itself).
|
||||||
* In case of a 'ParentID' change, relates to the new siblings under the new parent.
|
* In case of a 'ParentID' change, relates to the new siblings under the new parent.
|
||||||
*
|
*
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse JSON string with a
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function savetreenode($request)
|
public function savetreenode(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
if (!SecurityToken::inst()->checkRequest($request)) {
|
if (!SecurityToken::inst()->checkRequest($request)) {
|
||||||
return $this->httpError(400);
|
$this->httpError(400);
|
||||||
}
|
}
|
||||||
if (!$this->CanOrganiseSitetree()) {
|
if (!$this->CanOrganiseSitetree()) {
|
||||||
return $this->httpError(
|
$this->httpError(
|
||||||
403,
|
403,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.CANT_REORGANISE',
|
__CLASS__.'.CANT_REORGANISE',
|
||||||
@ -786,14 +770,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
$id = $request->requestVar('ID');
|
$id = $request->requestVar('ID');
|
||||||
$parentID = $request->requestVar('ParentID');
|
$parentID = $request->requestVar('ParentID');
|
||||||
if (!is_numeric($id) || !is_numeric($parentID)) {
|
if (!is_numeric($id) || !is_numeric($parentID)) {
|
||||||
return $this->httpError(400);
|
$this->httpError(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check record exists in the DB
|
// Check record exists in the DB
|
||||||
/** @var SiteTree $node */
|
/** @var SiteTree $node */
|
||||||
$node = DataObject::get_by_id($className, $id);
|
$node = DataObject::get_by_id($className, $id);
|
||||||
if (!$node) {
|
if (!$node) {
|
||||||
return $this->httpError(
|
$this->httpError(
|
||||||
500,
|
500,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.PLEASESAVE',
|
__CLASS__.'.PLEASESAVE',
|
||||||
@ -805,7 +789,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// Check top level permissions
|
// Check top level permissions
|
||||||
$root = $node->getParentType();
|
$root = $node->getParentType();
|
||||||
if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
|
if (($parentID == '0' || $root == 'root') && !SiteConfig::current_site_config()->canCreateTopLevel()) {
|
||||||
return $this->httpError(
|
$this->httpError(
|
||||||
403,
|
403,
|
||||||
_t(
|
_t(
|
||||||
__CLASS__.'.CANT_REORGANISE',
|
__CLASS__.'.CANT_REORGANISE',
|
||||||
@ -1000,7 +984,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Create the form
|
// Create the form
|
||||||
/** @skipUpgrade */
|
|
||||||
$form = Form::create(
|
$form = Form::create(
|
||||||
$this,
|
$this,
|
||||||
'SearchForm',
|
'SearchForm',
|
||||||
@ -1037,7 +1020,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $pageTypes;
|
return $pageTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doSearch($data, $form)
|
public function doSearch(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->getsubtree($this->getRequest());
|
return $this->getsubtree($this->getRequest());
|
||||||
}
|
}
|
||||||
@ -1352,8 +1335,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
|
// Added in-line to the form, but plucked into different view by LeftAndMain.Preview.js upon load
|
||||||
/** @skipUpgrade */
|
if (($record instanceof CMSPreviewable || $record->has_extension(CMSPreviewable::class))
|
||||||
if ($record instanceof CMSPreviewable && !$fields->fieldByName('SilverStripeNavigator')) {
|
&& !$fields->fieldByName('SilverStripeNavigator')
|
||||||
|
) {
|
||||||
$navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator());
|
$navField = new LiteralField('SilverStripeNavigator', $this->getSilverStripeNavigator());
|
||||||
$navField->setAllowHTML(true);
|
$navField->setAllowHTML(true);
|
||||||
$fields->push($navField);
|
$fields->push($navField);
|
||||||
@ -1404,7 +1388,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Announce the capability so the frontend can decide whether to allow preview or not.
|
// Announce the capability so the frontend can decide whether to allow preview or not.
|
||||||
if ($record instanceof CMSPreviewable) {
|
if ($record instanceof CMSPreviewable || $record->has_extension(CMSPreviewable::class)) {
|
||||||
$form->addExtraClass('cms-previewable');
|
$form->addExtraClass('cms-previewable');
|
||||||
}
|
}
|
||||||
$form->addExtraClass('fill-height flexbox-area-grow');
|
$form->addExtraClass('fill-height flexbox-area-grow');
|
||||||
@ -1560,17 +1544,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Callback to request the list of page types allowed under a given page instance.
|
* Callback to request the list of page types allowed under a given page instance.
|
||||||
* Provides a slower but more precise response over SiteTreeHints
|
* Provides a slower but more precise response over SiteTreeHints
|
||||||
*
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
*/
|
||||||
public function childfilter($request)
|
public function childfilter(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
// Check valid parent specified
|
// Check valid parent specified
|
||||||
$parentID = $request->requestVar('ParentID');
|
$parentID = $request->requestVar('ParentID');
|
||||||
$parent = SiteTree::get()->byID($parentID);
|
$parent = SiteTree::get()->byID($parentID);
|
||||||
if (!$parent || !$parent->exists()) {
|
if (!$parent || !$parent->exists()) {
|
||||||
return $this->httpError(404);
|
$this->httpError(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build hints specific to this class
|
// Build hints specific to this class
|
||||||
@ -1757,12 +1738,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Save and Publish page handler
|
* Save and Publish page handler
|
||||||
*
|
*
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function save($data, $form)
|
public function save(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->config()->get('tree_class');
|
||||||
|
|
||||||
@ -1905,12 +1883,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*
|
*
|
||||||
* @uses SiteTree->doRevertToLive()
|
* @uses SiteTree->doRevertToLive()
|
||||||
*
|
*
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function revert($data, $form)
|
public function revert(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
if (!isset($data['ID'])) {
|
if (!isset($data['ID'])) {
|
||||||
throw new HTTPResponse_Exception("Please pass an ID in the form content", 400);
|
throw new HTTPResponse_Exception("Please pass an ID in the form content", 400);
|
||||||
@ -1958,12 +1933,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*
|
*
|
||||||
* @see deletefromlive()
|
* @see deletefromlive()
|
||||||
*
|
*
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function delete($data, $form)
|
public function delete(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
$record = SiteTree::get()->byID($id);
|
$record = SiteTree::get()->byID($id);
|
||||||
@ -1993,12 +1965,9 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Delete this page from both live and stage
|
* Delete this page from both live and stage
|
||||||
*
|
*
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function archive($data, $form)
|
public function archive(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
/** @var SiteTree $record */
|
/** @var SiteTree $record */
|
||||||
@ -2026,14 +1995,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $this->getResponseNegotiator()->respond($this->getRequest());
|
return $this->getResponseNegotiator()->respond($this->getRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function publish($data, $form)
|
public function publish(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$data['publish'] = '1';
|
$data['publish'] = '1';
|
||||||
|
|
||||||
return $this->save($data, $form);
|
return $this->save($data, $form);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unpublish($data, $form)
|
public function unpublish(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$className = $this->config()->get('tree_class');
|
$className = $this->config()->get('tree_class');
|
||||||
/** @var SiteTree $record */
|
/** @var SiteTree $record */
|
||||||
@ -2168,87 +2137,10 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $this->batchactions()->batchActionList();
|
return $this->batchactions()->batchActionList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.12.0 Use custom logic instead
|
|
||||||
* @param $request
|
|
||||||
* @return HTTPResponse|string|void
|
|
||||||
*/
|
|
||||||
public function publishall($request)
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.12.0', 'Use custom logic instead');
|
|
||||||
if (!Permission::check('ADMIN')) {
|
|
||||||
return Security::permissionFailure($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment::increaseTimeLimitTo();
|
|
||||||
Environment::increaseMemoryLimitTo();
|
|
||||||
|
|
||||||
$response = "";
|
|
||||||
|
|
||||||
if (isset($this->requestParams['confirm'])) {
|
|
||||||
// Protect against CSRF on destructive action
|
|
||||||
if (!SecurityToken::inst()->checkRequest($request)) {
|
|
||||||
return $this->httpError(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = 0;
|
|
||||||
$pages = SiteTree::get()->limit("$start,30");
|
|
||||||
$count = 0;
|
|
||||||
while ($pages) {
|
|
||||||
/** @var SiteTree $page */
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
if ($page && !$page->canPublish()) {
|
|
||||||
return Security::permissionFailure($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->publishRecursive();
|
|
||||||
$page->destroy();
|
|
||||||
unset($page);
|
|
||||||
$count++;
|
|
||||||
$response .= "<li>$count</li>";
|
|
||||||
}
|
|
||||||
if ($pages->count() > 29) {
|
|
||||||
$start += 30;
|
|
||||||
$pages = SiteTree::get()->limit("$start,30");
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$response .= _t(__CLASS__ . '.PUBPAGES', "Done: Published {count} pages", ['count' => $count]);
|
|
||||||
} else {
|
|
||||||
$token = SecurityToken::inst();
|
|
||||||
$fields = new FieldList();
|
|
||||||
$token->updateFieldSet($fields);
|
|
||||||
$tokenField = $fields->first();
|
|
||||||
$tokenHtml = ($tokenField) ? $tokenField->FieldHolder() : '';
|
|
||||||
$publishAllDescription = _t(
|
|
||||||
__CLASS__ . '.PUBALLFUN2',
|
|
||||||
'Pressing this button will do the equivalent of going to every page and pressing "publish". '
|
|
||||||
. 'It\'s intended to be used after there have been massive edits of the content, such as when '
|
|
||||||
. 'the site was first built. '
|
|
||||||
. 'For large websites, this task might not be able to run through to completion. '
|
|
||||||
. 'In this case, we recommend talking to your developers to create a custom task'
|
|
||||||
);
|
|
||||||
$response .= '<h1>' . _t(__CLASS__ . '.PUBALLFUN', '"Publish All" functionality') . '</h1>
|
|
||||||
<p>' . $publishAllDescription . '</p>
|
|
||||||
<form method="post" action="publishall">
|
|
||||||
<input type="submit" name="confirm" value="'
|
|
||||||
. _t(__CLASS__ . '.PUBALLCONFIRM', "Please publish every page in the site, copying content stage to live", 'Confirmation button') .'" />'
|
|
||||||
. $tokenHtml .
|
|
||||||
'</form>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a completely deleted page from the SiteTree_versions table.
|
* Restore a completely deleted page from the SiteTree_versions table.
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
*/
|
||||||
public function restore($data, $form)
|
public function restore(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
if (!isset($data['ID']) || !is_numeric($data['ID'])) {
|
if (!isset($data['ID']) || !is_numeric($data['ID'])) {
|
||||||
return new HTTPResponse("Please pass an ID in the form content", 400);
|
return new HTTPResponse("Please pass an ID in the form content", 400);
|
||||||
@ -2275,7 +2167,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return $this->getResponseNegotiator()->respond($this->getRequest());
|
return $this->getResponseNegotiator()->respond($this->getRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function duplicate($request)
|
public function duplicate(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
// Protect against CSRF on destructive action
|
// Protect against CSRF on destructive action
|
||||||
if (!SecurityToken::inst()->checkRequest($request)) {
|
if (!SecurityToken::inst()->checkRequest($request)) {
|
||||||
@ -2319,11 +2211,11 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
return new HTTPResponse("CMSMain::duplicate() Bad ID: '$id'", 400);
|
return new HTTPResponse("CMSMain::duplicate() Bad ID: '$id'", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function duplicatewithchildren($request)
|
public function duplicatewithchildren(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
// Protect against CSRF on destructive action
|
// Protect against CSRF on destructive action
|
||||||
if (!SecurityToken::inst()->checkRequest($request)) {
|
if (!SecurityToken::inst()->checkRequest($request)) {
|
||||||
return $this->httpError(400);
|
$this->httpError(400);
|
||||||
}
|
}
|
||||||
Environment::increaseTimeLimitTo();
|
Environment::increaseTimeLimitTo();
|
||||||
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
if (($id = $this->urlParams['ID']) && is_numeric($id)) {
|
||||||
|
@ -192,12 +192,7 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function doAdd(array $data, Form $form): HTTPResponse
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
|
||||||
public function doAdd($data, $form)
|
|
||||||
{
|
{
|
||||||
$className = isset($data['PageType']) ? $data['PageType'] : "Page";
|
$className = isset($data['PageType']) ? $data['PageType'] : "Page";
|
||||||
$parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0;
|
$parentID = isset($data['ParentID']) ? (int)$data['ParentID'] : 0;
|
||||||
@ -241,7 +236,7 @@ class CMSPageAddController extends CMSPageEditController
|
|||||||
return $this->redirect(Controller::join_links($editController->Link('show'), $record->ID));
|
return $this->redirect(Controller::join_links($editController->Link('show'), $record->ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doCancel($data, $form)
|
public function doCancel(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
return $this->redirect(CMSMain::singleton()->Link());
|
return $this->redirect(CMSMain::singleton()->Link());
|
||||||
}
|
}
|
||||||
|
@ -53,30 +53,27 @@ class CMSPageEditController extends CMSMain
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Action handler for adding pages to a campaign
|
* Action handler for adding pages to a campaign
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
* @param Form $form
|
|
||||||
* @return DBHTMLText|HTTPResponse
|
|
||||||
*/
|
*/
|
||||||
public function addtocampaign($data, $form)
|
public function addtocampaign(array $data, Form $form): HTTPResponse
|
||||||
{
|
{
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
$record = \Page::get()->byID($id);
|
$record = \Page::get()->byID($id);
|
||||||
|
|
||||||
$handler = AddToCampaignHandler::create($this, $record);
|
$handler = AddToCampaignHandler::create($this, $record);
|
||||||
$results = $handler->addToCampaign($record, $data);
|
$response = $handler->addToCampaign($record, $data);
|
||||||
if (is_null($results)) {
|
$message = $response->getBody();
|
||||||
return null;
|
if (empty($message)) {
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getSchemaRequested()) {
|
if ($this->getSchemaRequested()) {
|
||||||
// Send extra "message" data with schema response
|
// Send extra "message" data with schema response
|
||||||
$extraData = ['message' => $results];
|
$extraData = ['message' => $message];
|
||||||
$schemaId = Controller::join_links($this->Link('schema/AddToCampaignForm'), $id);
|
$schemaId = Controller::join_links($this->Link('schema/AddToCampaignForm'), $id);
|
||||||
return $this->getSchemaResponse($schemaId, $form, null, $extraData);
|
return $this->getSchemaResponse($schemaId, $form, null, $extraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,480 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Admin\LeftAndMainFormRequestHandler;
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Control\HTTPRequest;
|
|
||||||
use SilverStripe\Control\HTTPResponse;
|
|
||||||
use SilverStripe\Forms\CheckboxField;
|
|
||||||
use SilverStripe\Forms\FieldList;
|
|
||||||
use SilverStripe\Forms\Form;
|
|
||||||
use SilverStripe\Forms\FormAction;
|
|
||||||
use SilverStripe\Forms\HiddenField;
|
|
||||||
use SilverStripe\Forms\HTMLReadonlyField;
|
|
||||||
use SilverStripe\Forms\LiteralField;
|
|
||||||
use SilverStripe\Forms\Tab;
|
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
use SilverStripe\Security\Security;
|
|
||||||
use SilverStripe\View\ArrayData;
|
|
||||||
use SilverStripe\View\ViewableData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Legacy CMS History controller. This functionality has been moved to the `silverstripe/versioned-admin` module and
|
|
||||||
* this class will be removed completly in SilverStripe 5.0.0.
|
|
||||||
* @deprecated 4.3.0 Use silverstripe/versioned-admin instead
|
|
||||||
*/
|
|
||||||
class CMSPageHistoryController extends CMSMain
|
|
||||||
{
|
|
||||||
|
|
||||||
private static $url_segment = 'pages/history';
|
|
||||||
|
|
||||||
private static $url_rule = '/$Action/$ID/$VersionID/$OtherVersionID';
|
|
||||||
|
|
||||||
private static $url_priority = 42;
|
|
||||||
|
|
||||||
private static $menu_title = 'History';
|
|
||||||
|
|
||||||
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
|
|
||||||
|
|
||||||
private static $allowed_actions = [
|
|
||||||
'EditForm',
|
|
||||||
'VersionsForm',
|
|
||||||
'CompareVersionsForm',
|
|
||||||
'show',
|
|
||||||
'compare'
|
|
||||||
];
|
|
||||||
|
|
||||||
private static $url_handlers = [
|
|
||||||
'$Action/$ID/$VersionID/$OtherVersionID' => 'handleAction',
|
|
||||||
'EditForm/$ID/$VersionID' => 'EditForm',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current version ID for this request. Can be 0 for latest version
|
|
||||||
*
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
protected $versionID = null;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice('4.3.0', 'Use silverstripe/versioned-admin instead', Deprecation::SCOPE_CLASS);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResponseNegotiator()
|
|
||||||
{
|
|
||||||
$negotiator = parent::getResponseNegotiator();
|
|
||||||
|
|
||||||
$negotiator->setCallback('CurrentForm', function () {
|
|
||||||
$form = $this->getEditForm();
|
|
||||||
if ($form) {
|
|
||||||
return $form->forTemplate();
|
|
||||||
}
|
|
||||||
return $this->renderWith($this->getTemplatesWithSuffix('_Content'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$negotiator->setCallback('default', function () {
|
|
||||||
return $this->renderWith($this->getViewer('show'));
|
|
||||||
});
|
|
||||||
|
|
||||||
return $negotiator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
|
||||||
public function show($request)
|
|
||||||
{
|
|
||||||
// Record id and version for this request
|
|
||||||
$id = $request->param('ID');
|
|
||||||
$this->setCurrentPageID($id);
|
|
||||||
$versionID = $request->param('VersionID');
|
|
||||||
$this->setVersionID($versionID);
|
|
||||||
|
|
||||||
// Show id
|
|
||||||
$form = $this->getEditForm();
|
|
||||||
|
|
||||||
$negotiator = $this->getResponseNegotiator();
|
|
||||||
$negotiator->setCallback('CurrentForm', function () use ($form) {
|
|
||||||
return $form
|
|
||||||
? $form->forTemplate()
|
|
||||||
: $this->renderWith($this->getTemplatesWithSuffix('_Content'));
|
|
||||||
});
|
|
||||||
$negotiator->setCallback('default', function () use ($form) {
|
|
||||||
return $this
|
|
||||||
->customise(['EditForm' => $form])
|
|
||||||
->renderWith($this->getViewer('show'));
|
|
||||||
});
|
|
||||||
|
|
||||||
return $negotiator->respond($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
|
||||||
public function compare($request)
|
|
||||||
{
|
|
||||||
$form = $this->CompareVersionsForm(
|
|
||||||
$request->param('VersionID'),
|
|
||||||
$request->param('OtherVersionID')
|
|
||||||
);
|
|
||||||
|
|
||||||
$negotiator = $this->getResponseNegotiator();
|
|
||||||
$negotiator->setCallback('CurrentForm', function () use ($form) {
|
|
||||||
return $form ? $form->forTemplate() : $this->renderWith($this->getTemplatesWithSuffix('_Content'));
|
|
||||||
});
|
|
||||||
$negotiator->setCallback('default', function () use ($form) {
|
|
||||||
return $this->customise(['EditForm' => $form])->renderWith($this->getViewer('show'));
|
|
||||||
});
|
|
||||||
|
|
||||||
return $negotiator->respond($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSilverStripeNavigator()
|
|
||||||
{
|
|
||||||
$record = $this->getRecord($this->currentPageID(), $this->getRequest()->param('VersionID'));
|
|
||||||
if ($record) {
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
return $navigator->renderWith($this->getTemplatesWithSuffix('_SilverStripeNavigator'));
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return Form
|
|
||||||
*/
|
|
||||||
public function EditForm($request = null)
|
|
||||||
{
|
|
||||||
if ($request) {
|
|
||||||
// Validate VersionID is present
|
|
||||||
$versionID = $request->param('VersionID');
|
|
||||||
if (!isset($versionID)) {
|
|
||||||
$this->httpError(400);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$this->setVersionID($versionID);
|
|
||||||
}
|
|
||||||
return parent::EditForm($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the read only version of the edit form. Detaches all {@link FormAction}
|
|
||||||
* instances attached since only action relates to revert.
|
|
||||||
*
|
|
||||||
* Permission checking is done at the {@link CMSMain::getEditForm()} level.
|
|
||||||
*
|
|
||||||
* @param int $id ID of the record to show
|
|
||||||
* @param array $fields optional
|
|
||||||
* @param int $versionID
|
|
||||||
* @param int $compareID Compare mode
|
|
||||||
*
|
|
||||||
* @return Form
|
|
||||||
*/
|
|
||||||
public function getEditForm($id = null, $fields = null, $versionID = null, $compareID = null)
|
|
||||||
{
|
|
||||||
if (!$id) {
|
|
||||||
$id = $this->currentPageID();
|
|
||||||
}
|
|
||||||
if (!$versionID) {
|
|
||||||
$versionID = $this->getVersionID();
|
|
||||||
}
|
|
||||||
|
|
||||||
$record = $this->getRecord($id, $versionID);
|
|
||||||
if (!$record) {
|
|
||||||
return $this->EmptyForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh version ID
|
|
||||||
$versionID = $record->Version;
|
|
||||||
$this->setVersionID($versionID);
|
|
||||||
|
|
||||||
// Get edit form
|
|
||||||
$form = parent::getEditForm($record, $record->getCMSFields());
|
|
||||||
// Respect permission failures from parent implementation
|
|
||||||
if (!($form instanceof Form)) {
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move to the SilverStripeNavigator structure so the new preview can pick it up.
|
|
||||||
//$nav = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
|
|
||||||
$actions = new FieldList(
|
|
||||||
$revert = FormAction::create(
|
|
||||||
'doRollback',
|
|
||||||
_t('SilverStripe\\CMS\\Controllers\\CMSPageHistoryController.REVERTTOTHISVERSION', 'Revert to this version')
|
|
||||||
)
|
|
||||||
->setUseButtonTag(true)
|
|
||||||
->addExtraClass('btn-warning font-icon-back-in-time')
|
|
||||||
);
|
|
||||||
$actions->setForm($form);
|
|
||||||
$form->setActions($actions);
|
|
||||||
|
|
||||||
$fields = $form->Fields();
|
|
||||||
$fields->removeByName("Status");
|
|
||||||
$fields->push(new HiddenField("ID"));
|
|
||||||
$fields->push(new HiddenField("Version"));
|
|
||||||
|
|
||||||
$fields = $fields->makeReadonly();
|
|
||||||
|
|
||||||
if ($compareID) {
|
|
||||||
$link = Controller::join_links(
|
|
||||||
$this->Link('show'),
|
|
||||||
$id
|
|
||||||
);
|
|
||||||
|
|
||||||
$view = _t(__CLASS__ . '.VIEW', "view");
|
|
||||||
|
|
||||||
$message = _t(
|
|
||||||
__CLASS__ . '.COMPARINGVERSION',
|
|
||||||
"Comparing versions {version1} and {version2}.",
|
|
||||||
[
|
|
||||||
'version1' => sprintf('%s (<a href="%s">%s</a>)', $versionID, Controller::join_links($link, $versionID), $view),
|
|
||||||
'version2' => sprintf('%s (<a href="%s">%s</a>)', $compareID, Controller::join_links($link, $compareID), $view)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$revert->setReadonly(true);
|
|
||||||
} else {
|
|
||||||
if ($record->isLatestVersion()) {
|
|
||||||
$message = _t(__CLASS__ . '.VIEWINGLATEST', 'Currently viewing the latest version.');
|
|
||||||
} else {
|
|
||||||
$message = _t(
|
|
||||||
__CLASS__ . '.VIEWINGVERSION',
|
|
||||||
"Currently viewing version {version}.",
|
|
||||||
['version' => $versionID]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var Tab $mainTab */
|
|
||||||
$mainTab = $fields->fieldByName('Root.Main');
|
|
||||||
$mainTab->unshift(
|
|
||||||
LiteralField::create('CurrentlyViewingMessage', ArrayData::create([
|
|
||||||
'Content' => DBField::create_field('HTMLFragment', $message),
|
|
||||||
'Classes' => 'alert alert-info'
|
|
||||||
])->renderWith($this->getTemplatesWithSuffix('_notice')))
|
|
||||||
);
|
|
||||||
|
|
||||||
$form->setFields($fields->makeReadonly());
|
|
||||||
$form->loadDataFrom([
|
|
||||||
"ID" => $id,
|
|
||||||
"Version" => $versionID,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($record->isLatestVersion()) {
|
|
||||||
$revert->setReadonly(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$form->removeExtraClass('cms-content');
|
|
||||||
|
|
||||||
// History form has both ID and VersionID as suffixes
|
|
||||||
$form->setRequestHandler(
|
|
||||||
LeftAndMainFormRequestHandler::create($form, [$id, $versionID])
|
|
||||||
);
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version select form. Main interface between selecting versions to view
|
|
||||||
* and comparing multiple versions.
|
|
||||||
*
|
|
||||||
* Because we can reload the page directly to a compare view (history/compare/1/2/3)
|
|
||||||
* this form has to adapt to those parameters as well.
|
|
||||||
*
|
|
||||||
* @return Form
|
|
||||||
*/
|
|
||||||
public function VersionsForm()
|
|
||||||
{
|
|
||||||
$id = $this->currentPageID();
|
|
||||||
$page = $this->getRecord($id);
|
|
||||||
$versionsHtml = '';
|
|
||||||
|
|
||||||
$action = $this->getRequest()->param('Action');
|
|
||||||
$versionID = $this->getRequest()->param('VersionID');
|
|
||||||
$otherVersionID = $this->getRequest()->param('OtherVersionID');
|
|
||||||
|
|
||||||
$showUnpublishedChecked = 0;
|
|
||||||
$compareModeChecked = ($action == "compare");
|
|
||||||
|
|
||||||
if ($page) {
|
|
||||||
$versions = $page->Versions();
|
|
||||||
$versionID = (!$versionID) ? $page->Version : $versionID;
|
|
||||||
|
|
||||||
if ($versions) {
|
|
||||||
foreach ($versions as $k => $version) {
|
|
||||||
$active = false;
|
|
||||||
|
|
||||||
if ($version->Version == $versionID || $version->Version == $otherVersionID) {
|
|
||||||
$active = true;
|
|
||||||
|
|
||||||
if (!$version->WasPublished) {
|
|
||||||
$showUnpublishedChecked = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$version->Active = ($active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$vd = new ViewableData();
|
|
||||||
|
|
||||||
$versionsHtml = $vd->customise([
|
|
||||||
'Versions' => $versions
|
|
||||||
])->renderWith($this->getTemplatesWithSuffix('_versions'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$fields = new FieldList(
|
|
||||||
new CheckboxField(
|
|
||||||
'ShowUnpublished',
|
|
||||||
_t('SilverStripe\\CMS\\Controllers\\CMSPageHistoryController.SHOWUNPUBLISHED', 'Show unpublished versions'),
|
|
||||||
$showUnpublishedChecked
|
|
||||||
),
|
|
||||||
new CheckboxField(
|
|
||||||
'CompareMode',
|
|
||||||
_t('SilverStripe\\CMS\\Controllers\\CMSPageHistoryController.COMPAREMODE', 'Compare mode (select two)'),
|
|
||||||
$compareModeChecked
|
|
||||||
),
|
|
||||||
new LiteralField('VersionsHtml', $versionsHtml),
|
|
||||||
$hiddenID = new HiddenField('ID', false, "")
|
|
||||||
);
|
|
||||||
|
|
||||||
$form = Form::create(
|
|
||||||
$this,
|
|
||||||
'VersionsForm',
|
|
||||||
$fields,
|
|
||||||
new FieldList()
|
|
||||||
)->setHTMLID('Form_VersionsForm');
|
|
||||||
$form->loadDataFrom($this->getRequest()->requestVars());
|
|
||||||
$hiddenID->setValue($id);
|
|
||||||
$form->unsetValidator();
|
|
||||||
|
|
||||||
$form
|
|
||||||
->addExtraClass('cms-versions-form') // placeholder, necessary for $.metadata() to work
|
|
||||||
->setAttribute('data-link-tmpl-compare', Controller::join_links($this->Link('compare'), '%s', '%s', '%s'))
|
|
||||||
->setAttribute('data-link-tmpl-show', Controller::join_links($this->Link('show'), '%s', '%s'));
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $versionID
|
|
||||||
* @param int $otherVersionID
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function CompareVersionsForm($versionID, $otherVersionID)
|
|
||||||
{
|
|
||||||
if ($versionID > $otherVersionID) {
|
|
||||||
$toVersion = $versionID;
|
|
||||||
$fromVersion = $otherVersionID;
|
|
||||||
} else {
|
|
||||||
$toVersion = $otherVersionID;
|
|
||||||
$fromVersion = $versionID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$toVersion || !$fromVersion) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $this->currentPageID();
|
|
||||||
/** @var SiteTree $page */
|
|
||||||
$page = SiteTree::get()->byID($id);
|
|
||||||
|
|
||||||
$record = null;
|
|
||||||
if ($page && $page->exists()) {
|
|
||||||
if (!$page->canView()) {
|
|
||||||
return Security::permissionFailure($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
$record = $page->compareVersions($fromVersion, $toVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
$fromVersionRecord = Versioned::get_version(SiteTree::class, $id, $fromVersion);
|
|
||||||
$toVersionRecord = Versioned::get_version(SiteTree::class, $id, $toVersion);
|
|
||||||
|
|
||||||
if (!$fromVersionRecord) {
|
|
||||||
throw new \Exception("Can't find version $fromVersion of page $id");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$toVersionRecord) {
|
|
||||||
throw new \Exception("Can't find version $toVersion of page $id");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$record) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$form = $this->getEditForm($id, null, $fromVersion, $toVersion);
|
|
||||||
$form->setActions(new FieldList());
|
|
||||||
$form->addExtraClass('compare');
|
|
||||||
|
|
||||||
$form->loadDataFrom($record);
|
|
||||||
$form->loadDataFrom([
|
|
||||||
"ID" => $id,
|
|
||||||
"Version" => $fromVersion,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Comparison views shouldn't be editable.
|
|
||||||
// As the comparison output is HTML and not valid values for the various field types
|
|
||||||
$readonlyFields = $this->transformReadonly($form->Fields());
|
|
||||||
$form->setFields($readonlyFields);
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace all data fields with HTML readonly fields to display diff
|
|
||||||
*
|
|
||||||
* @param FieldList $fields
|
|
||||||
* @return FieldList
|
|
||||||
*/
|
|
||||||
public function transformReadonly(FieldList $fields)
|
|
||||||
{
|
|
||||||
foreach ($fields->dataFields() as $field) {
|
|
||||||
if ($field instanceof HiddenField) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$newField = $field->castedCopy(HTMLReadonlyField::class);
|
|
||||||
$fields->replaceField($field->getName(), $newField);
|
|
||||||
}
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set current version ID
|
|
||||||
*
|
|
||||||
* @param int $versionID
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setVersionID($versionID)
|
|
||||||
{
|
|
||||||
$this->versionID = $versionID;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current version ID
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getVersionID()
|
|
||||||
{
|
|
||||||
return $this->versionID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTabIdentifier()
|
|
||||||
{
|
|
||||||
return 'history';
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\Admin\Navigator\SilverStripeNavigator;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
@ -29,7 +30,6 @@ use SilverStripe\View\ArrayData;
|
|||||||
use SilverStripe\View\Parsers\URLSegmentFilter;
|
use SilverStripe\View\Parsers\URLSegmentFilter;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\View\SSViewer;
|
use SilverStripe\View\SSViewer;
|
||||||
use Translatable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The most common kind of controller; effectively a controller linked to a {@link DataObject}.
|
* The most common kind of controller; effectively a controller linked to a {@link DataObject}.
|
||||||
@ -175,7 +175,6 @@ class ContentController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check page permissions
|
// Check page permissions
|
||||||
/** @skipUpgrade */
|
|
||||||
if ($this->dataRecord && $this->URLSegment != 'Security' && !$this->dataRecord->canView()) {
|
if ($this->dataRecord && $this->URLSegment != 'Security' && !$this->dataRecord->canView()) {
|
||||||
Security::permissionFailure($this);
|
Security::permissionFailure($this);
|
||||||
return;
|
return;
|
||||||
@ -186,11 +185,9 @@ class ContentController extends Controller
|
|||||||
* This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
|
* This acts the same as {@link Controller::handleRequest()}, but if an action cannot be found this will attempt to
|
||||||
* fall over to a child controller in order to provide functionality for nested URLs.
|
* fall over to a child controller in order to provide functionality for nested URLs.
|
||||||
*
|
*
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function handleRequest(HTTPRequest $request)
|
public function handleRequest(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
/** @var SiteTree $child */
|
/** @var SiteTree $child */
|
||||||
$child = null;
|
$child = null;
|
||||||
@ -200,11 +197,6 @@ class ContentController extends Controller
|
|||||||
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
|
// control to a child controller. This allows for the creation of chains of controllers which correspond to a
|
||||||
// nested URL.
|
// nested URL.
|
||||||
if ($action && SiteTree::config()->nested_urls && !$this->hasAction($action)) {
|
if ($action && SiteTree::config()->nested_urls && !$this->hasAction($action)) {
|
||||||
// See ModelAdController->getNestedController() for similar logic
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
Translatable::disable_locale_filter();
|
|
||||||
}
|
|
||||||
|
|
||||||
$filter = URLSegmentFilter::create();
|
$filter = URLSegmentFilter::create();
|
||||||
|
|
||||||
// look for a page with this URLSegment
|
// look for a page with this URLSegment
|
||||||
@ -213,10 +205,6 @@ class ContentController extends Controller
|
|||||||
// url encode unless it's multibyte (already pre-encoded in the database)
|
// url encode unless it's multibyte (already pre-encoded in the database)
|
||||||
'URLSegment' => $filter->getAllowMultibyte() ? $action : rawurlencode($action),
|
'URLSegment' => $filter->getAllowMultibyte() ? $action : rawurlencode($action),
|
||||||
])->first();
|
])->first();
|
||||||
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
Translatable::enable_locale_filter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we found a page with this URLSegment.
|
// we found a page with this URLSegment.
|
||||||
@ -226,25 +214,6 @@ class ContentController extends Controller
|
|||||||
|
|
||||||
$response = ModelAsController::controller_for($child)->handleRequest($request);
|
$response = ModelAsController::controller_for($child)->handleRequest($request);
|
||||||
} else {
|
} else {
|
||||||
// If a specific locale is requested, and it doesn't match the page found by URLSegment,
|
|
||||||
// look for a translation and redirect (see #5001). Only happens on the last child in
|
|
||||||
// a potentially nested URL chain.
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
$locale = $request->getVar('locale');
|
|
||||||
if ($locale
|
|
||||||
&& i18n::getData()->validate($locale)
|
|
||||||
&& $this->dataRecord
|
|
||||||
&& $this->dataRecord->Locale != $locale
|
|
||||||
) {
|
|
||||||
$translation = $this->dataRecord->getTranslation($locale);
|
|
||||||
if ($translation) {
|
|
||||||
$response = new HTTPResponse();
|
|
||||||
$response->redirect($translation->Link(), 301);
|
|
||||||
throw new HTTPResponse_Exception($response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Director::set_current_page($this->data());
|
Director::set_current_page($this->data());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -416,9 +385,6 @@ HTML;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an RFC1766 compliant locale string, e.g. 'fr-CA'.
|
* Returns an RFC1766 compliant locale string, e.g. 'fr-CA'.
|
||||||
* Inspects the associated {@link dataRecord} for a {@link SiteTree->Locale} value if present,
|
|
||||||
* and falls back to {@link Translatable::get_current_locale()} or {@link i18n::default_locale()},
|
|
||||||
* depending if Translatable is enabled.
|
|
||||||
*
|
*
|
||||||
* Suitable for insertion into lang= and xml:lang=
|
* Suitable for insertion into lang= and xml:lang=
|
||||||
* attributes in HTML or XHTML output.
|
* attributes in HTML or XHTML output.
|
||||||
@ -427,14 +393,7 @@ HTML;
|
|||||||
*/
|
*/
|
||||||
public function ContentLocale()
|
public function ContentLocale()
|
||||||
{
|
{
|
||||||
if ($this->dataRecord && $this->dataRecord->hasExtension('Translatable')) {
|
$locale = i18n::get_locale();
|
||||||
$locale = $this->dataRecord->Locale;
|
|
||||||
} elseif (class_exists('Translatable') && SiteTree::has_extension('Translatable')) {
|
|
||||||
$locale = Translatable::get_current_locale();
|
|
||||||
} else {
|
|
||||||
$locale = i18n::get_locale();
|
|
||||||
}
|
|
||||||
|
|
||||||
return i18n::convert_rfc1766($locale);
|
return i18n::convert_rfc1766($locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ use SilverStripe\Dev\Debug;
|
|||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\View\Parsers\URLSegmentFilter;
|
use SilverStripe\View\Parsers\URLSegmentFilter;
|
||||||
use Translatable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ModelAsController deals with mapping the initial request to the first {@link SiteTree}/{@link ContentController}
|
* ModelAsController deals with mapping the initial request to the first {@link SiteTree}/{@link ContentController}
|
||||||
@ -33,11 +32,9 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
* Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and
|
* Get the appropriate {@link ContentController} for handling a {@link SiteTree} object, link it to the object and
|
||||||
* return it.
|
* return it.
|
||||||
*
|
*
|
||||||
* @param SiteTree $sitetree
|
|
||||||
* @param string $action
|
* @param string $action
|
||||||
* @return ContentController
|
|
||||||
*/
|
*/
|
||||||
public static function controller_for(SiteTree $sitetree, $action = null)
|
public static function controller_for(SiteTree $sitetree, $action = null): ContentController
|
||||||
{
|
{
|
||||||
$controller = $sitetree->getControllerName();
|
$controller = $sitetree->getControllerName();
|
||||||
|
|
||||||
@ -58,7 +55,6 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
{
|
{
|
||||||
parent::beforeHandleRequest($request);
|
parent::beforeHandleRequest($request);
|
||||||
// If the database has not yet been created, redirect to the build page.
|
// If the database has not yet been created, redirect to the build page.
|
||||||
/** @skipUpgrade */
|
|
||||||
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
||||||
$this->getResponse()->redirect(Controller::join_links(
|
$this->getResponse()->redirect(Controller::join_links(
|
||||||
Director::absoluteBaseURL(),
|
Director::absoluteBaseURL(),
|
||||||
@ -72,10 +68,8 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @uses ModelAsController::getNestedController()
|
* @uses ModelAsController::getNestedController()
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
*/
|
||||||
public function handleRequest(HTTPRequest $request)
|
public function handleRequest(HTTPRequest $request): HTTPResponse
|
||||||
{
|
{
|
||||||
$this->beforeHandleRequest($request);
|
$this->beforeHandleRequest($request);
|
||||||
|
|
||||||
@ -86,23 +80,16 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the database has not yet been created, redirect to the build page.
|
// If the database has not yet been created, redirect to the build page.
|
||||||
/** @skipUpgrade */
|
|
||||||
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
||||||
$this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
|
$this->getResponse()->redirect(Controller::join_links(Director::absoluteBaseURL(), 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null)));
|
||||||
$this->popCurrent();
|
$this->popCurrent();
|
||||||
|
|
||||||
return $this->getResponse();
|
return $this->getResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$result = $this->getNestedController();
|
$result = $this->getNestedController()->handleRequest($this->getRequest());
|
||||||
|
$result = $result;
|
||||||
if ($result instanceof RequestHandler) {
|
|
||||||
$result = $result->handleRequest($this->getRequest());
|
|
||||||
} elseif (!($result instanceof HTTPResponse)) {
|
|
||||||
user_error("ModelAsController::getNestedController() returned bad object type '" .
|
|
||||||
get_class($result)."'", E_USER_WARNING);
|
|
||||||
}
|
|
||||||
} catch (HTTPResponse_Exception $responseException) {
|
} catch (HTTPResponse_Exception $responseException) {
|
||||||
$result = $responseException->getResponse();
|
$result = $responseException->getResponse();
|
||||||
}
|
}
|
||||||
@ -112,10 +99,9 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ContentController
|
|
||||||
* @throws Exception If URLSegment not passed in as a request parameter.
|
* @throws Exception If URLSegment not passed in as a request parameter.
|
||||||
*/
|
*/
|
||||||
public function getNestedController()
|
public function getNestedController(): ContentController
|
||||||
{
|
{
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
|
||||||
@ -123,11 +109,6 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
|
throw new Exception('ModelAsController->getNestedController(): was not passed a URLSegment value.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find page by link, regardless of current locale settings
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
Translatable::disable_locale_filter();
|
|
||||||
}
|
|
||||||
|
|
||||||
// url encode unless it's multibyte (already pre-encoded in the database)
|
// url encode unless it's multibyte (already pre-encoded in the database)
|
||||||
$filter = URLSegmentFilter::create();
|
$filter = URLSegmentFilter::create();
|
||||||
if (!$filter->getAllowMultibyte()) {
|
if (!$filter->getAllowMultibyte()) {
|
||||||
@ -143,21 +124,10 @@ class ModelAsController extends Controller implements NestedController
|
|||||||
/** @var SiteTree $sitetree */
|
/** @var SiteTree $sitetree */
|
||||||
$sitetree = DataObject::get_one(SiteTree::class, $conditions);
|
$sitetree = DataObject::get_one(SiteTree::class, $conditions);
|
||||||
|
|
||||||
// Check translation module
|
|
||||||
// @todo Refactor out module specific code
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
Translatable::enable_locale_filter();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$sitetree) {
|
if (!$sitetree) {
|
||||||
$this->httpError(404, 'The requested page could not be found.');
|
$this->httpError(404, 'The requested page could not be found.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce current locale setting to the loaded SiteTree object
|
|
||||||
if (class_exists('Translatable') && $sitetree->Locale) {
|
|
||||||
Translatable::set_current_locale($sitetree->Locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_REQUEST['debug'])) {
|
if (isset($_REQUEST['debug'])) {
|
||||||
Debug::message("Using record #$sitetree->ID of type " . get_class($sitetree) . " with link {$sitetree->Link()}");
|
Debug::message("Using record #$sitetree->ID of type " . get_class($sitetree) . " with link {$sitetree->Link()}");
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,9 @@ class OldPageRedirector extends Extension
|
|||||||
* On every URL that generates a 404, we'll capture it here and see if we can
|
* On every URL that generates a 404, we'll capture it here and see if we can
|
||||||
* find an old URL that it should be redirecting to.
|
* find an old URL that it should be redirecting to.
|
||||||
*
|
*
|
||||||
* @param HTTPRequest $request The request object
|
|
||||||
* @throws HTTPResponse_Exception
|
* @throws HTTPResponse_Exception
|
||||||
*/
|
*/
|
||||||
public function onBeforeHTTPError404($request)
|
public function onBeforeHTTPError404(HTTPRequest $request)
|
||||||
{
|
{
|
||||||
// We need to get the URL ourselves because $request->allParams() only has a max of 4 params
|
// We need to get the URL ourselves because $request->allParams() only has a max of 4 params
|
||||||
$params = preg_split('|/+|', $request->getURL() ?? '');
|
$params = preg_split('|/+|', $request->getURL() ?? '');
|
||||||
@ -103,7 +102,7 @@ class OldPageRedirector extends Extension
|
|||||||
// No valid page found.
|
// No valid page found.
|
||||||
if ($redirect) {
|
if ($redirect) {
|
||||||
// If we had some redirect to be done, lets do it. imagine /foo/action -> /bar/action, we still want this redirect to happen if action isn't a page
|
// If we had some redirect to be done, lets do it. imagine /foo/action -> /bar/action, we still want this redirect to happen if action isn't a page
|
||||||
return $page->Link() . implode('/', $params);
|
return Controller::join_links($page->Link(), implode('/', $params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,7 +73,6 @@ class RootURLController extends Controller implements Resettable
|
|||||||
|
|
||||||
self::$is_at_root = true;
|
self::$is_at_root = true;
|
||||||
|
|
||||||
/** @skipUpgrade */
|
|
||||||
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
||||||
$this->getResponse()->redirect(Controller::join_links(
|
$this->getResponse()->redirect(Controller::join_links(
|
||||||
Director::absoluteBaseURL(),
|
Director::absoluteBaseURL(),
|
||||||
@ -85,17 +84,12 @@ class RootURLController extends Controller implements Resettable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function handleRequest(HTTPRequest $request): HTTPResponse
|
||||||
* @param HTTPRequest $request
|
|
||||||
* @return HTTPResponse
|
|
||||||
*/
|
|
||||||
public function handleRequest(HTTPRequest $request)
|
|
||||||
{
|
{
|
||||||
self::$is_at_root = true;
|
self::$is_at_root = true;
|
||||||
$this->beforeHandleRequest($request);
|
$this->beforeHandleRequest($request);
|
||||||
|
|
||||||
if (!$this->getResponse()->isFinished()) {
|
if (!$this->getResponse()->isFinished()) {
|
||||||
/** @skipUpgrade */
|
|
||||||
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
if (!DB::is_active() || !ClassInfo::hasTable('SiteTree')) {
|
||||||
$this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
|
$this->getResponse()->redirect(Director::absoluteBaseURL() . 'dev/build?returnURL=' . (isset($_GET['url']) ? urlencode($_GET['url']) : null));
|
||||||
return $this->getResponse();
|
return $this->getResponse();
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\Core\ClassInfo;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\ArrayList;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\ORM\SS_List;
|
|
||||||
use SilverStripe\View\ViewableData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class representing links to different views of a record
|
|
||||||
* for CMS authors, usually for {@link SiteTree} objects with "stage" and "live" links.
|
|
||||||
* Useful both in the CMS and alongside the page template (for logged in authors).
|
|
||||||
* The class can be used for any {@link DataObject} subclass implementing the {@link CMSPreviewable} interface.
|
|
||||||
*
|
|
||||||
* New item types can be defined by extending the {@link SilverStripeNavigatorItem} class,
|
|
||||||
* for example the "cmsworkflow" module defines a new "future state" item with a date selector
|
|
||||||
* to view embargoed data at a future point in time. So the item doesn't always have to be a simple link.
|
|
||||||
*
|
|
||||||
* Class will be moved from `silverstripe/cms` to `silverstripe/admin`
|
|
||||||
* @deprecated 4.13.0 Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigator
|
|
||||||
*/
|
|
||||||
class SilverStripeNavigator extends ViewableData
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var DataObject|\SilverStripe\ORM\CMSPreviewable
|
|
||||||
*/
|
|
||||||
protected $record;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DataObject|\SilverStripe\ORM\CMSPreviewable $record
|
|
||||||
*/
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigator',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
});
|
|
||||||
parent::__construct();
|
|
||||||
$this->record = $record;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return SS_List of SilverStripeNavigatorItem
|
|
||||||
*/
|
|
||||||
public function getItems()
|
|
||||||
{
|
|
||||||
$items = [];
|
|
||||||
|
|
||||||
$classes = ClassInfo::subclassesFor(SilverStripeNavigatorItem::class);
|
|
||||||
array_shift($classes);
|
|
||||||
|
|
||||||
// Sort menu items according to priority
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
/** @var SilverStripeNavigatorItem $item */
|
|
||||||
$item = new $class($this->record);
|
|
||||||
if (!$item->canView()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This funny litle formula ensures that the first item added with the same priority will be left-most.
|
|
||||||
$priority = $item->getPriority() * 100 - 1;
|
|
||||||
|
|
||||||
// Ensure that we can have duplicates with the same (default) priority
|
|
||||||
while (isset($items[$priority])) {
|
|
||||||
$priority++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$items[$priority] = $item;
|
|
||||||
}
|
|
||||||
ksort($items);
|
|
||||||
|
|
||||||
// Drop the keys and let the ArrayList handle the numbering, so $IsFirst, $IsLast and others work properly.
|
|
||||||
return new ArrayList(array_values($items ?? []));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return DataObject|\SilverStripe\ORM\CMSPreviewable
|
|
||||||
*/
|
|
||||||
public function getRecord()
|
|
||||||
{
|
|
||||||
return $this->record;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DataObject|CMSPreviewable $record
|
|
||||||
* @return array template data
|
|
||||||
*/
|
|
||||||
public static function get_for_record($record)
|
|
||||||
{
|
|
||||||
$html = '';
|
|
||||||
$message = '';
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$items = $navigator->getItems();
|
|
||||||
foreach ($items as $item) {
|
|
||||||
$text = $item->getHTML();
|
|
||||||
if ($text) {
|
|
||||||
$html .= $text;
|
|
||||||
}
|
|
||||||
$newMessage = $item->getMessage();
|
|
||||||
if ($newMessage && $item->isActive()) {
|
|
||||||
$message = $newMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'items' => $html,
|
|
||||||
'message' => $message
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
use SilverStripe\Security\Member;
|
|
||||||
use SilverStripe\View\ViewableData;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigator items are links that appear in the $SilverStripeNavigator bar.
|
|
||||||
* To add an item, extend this class - it will be automatically picked up.
|
|
||||||
* When instanciating items manually, please ensure to call {@link canView()}.
|
|
||||||
*
|
|
||||||
* Class have been moved from `silverstripe/cms` to `silverstripe/admin` and renamed.
|
|
||||||
* @deprecated Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigatorItem
|
|
||||||
*/
|
|
||||||
abstract class SilverStripeNavigatorItem extends ViewableData
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DataObject|CMSPreviewable
|
|
||||||
*/
|
|
||||||
protected $record;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
protected $recordLink;
|
|
||||||
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
switch (static::class) {
|
|
||||||
// These classes have their own deprecation notice
|
|
||||||
case 'SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_ArchiveLink':
|
|
||||||
case 'SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_LiveLink':
|
|
||||||
case 'SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_StageLink':
|
|
||||||
case 'SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_Unversioned':
|
|
||||||
// This class is not deprecated and doesn't have a deprecation notice
|
|
||||||
case 'SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_CMSLink':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigatorItem',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
parent::__construct();
|
|
||||||
$this->record = $record;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string HTML, mostly a link - but can be more complex as well.
|
|
||||||
* For example, a "future state" item might show a date selector.
|
|
||||||
*/
|
|
||||||
abstract public function getHTML();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
* Get the Title of an item
|
|
||||||
*/
|
|
||||||
abstract public function getTitle();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Machine-friendly name.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getName()
|
|
||||||
{
|
|
||||||
return substr(static::class, strpos(static::class, '_') + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional link to a specific view of this record.
|
|
||||||
* Not all items are simple links, please use {@link getHTML()}
|
|
||||||
* to represent an item in markup unless you know what you're doing.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLink()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMessage()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return DataObject
|
|
||||||
*/
|
|
||||||
public function getRecord()
|
|
||||||
{
|
|
||||||
return $this->record;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getPriority()
|
|
||||||
{
|
|
||||||
return $this->config()->get('priority');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As items might convey different record states like a "stage" or "live" table,
|
|
||||||
* an item can be active (showing the record in this state).
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function isActive()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters items based on member permissions or other criteria,
|
|
||||||
* such as if a state is generally available for the current record.
|
|
||||||
*
|
|
||||||
* @param Member $member
|
|
||||||
* @return Boolean
|
|
||||||
*/
|
|
||||||
public function canView($member = null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Counts as "archived" if the current record is a different version from both live and draft.
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function isArchived()
|
|
||||||
{
|
|
||||||
/** @var Versioned|DataObject $record */
|
|
||||||
$record = $this->record;
|
|
||||||
if (!$record->hasExtension(Versioned::class) || !$record->hasStages()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($record->_cached_isArchived)) {
|
|
||||||
$record->_cached_isArchived = $record->isArchived();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $record->_cached_isArchived;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
|
||||||
use SilverStripe\ORM\FieldType\DBField;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class will be moved from `silverstripe/cms` to `silverstripe/admin`
|
|
||||||
* @deprecated 4.13.0 Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_ArchiveLink
|
|
||||||
*/
|
|
||||||
class SilverStripeNavigatorItem_ArchiveLink extends SilverStripeNavigatorItem
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param DataObject|CMSPreviewable $record
|
|
||||||
*/
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_ArchiveLink',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
});
|
|
||||||
parent::__construct($record);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @config */
|
|
||||||
private static $priority = 40;
|
|
||||||
|
|
||||||
public function getHTML()
|
|
||||||
{
|
|
||||||
$linkClass = $this->isActive() ? 'ss-ui-button current' : 'ss-ui-button';
|
|
||||||
$linkTitle = _t('SilverStripe\\CMS\\Controllers\\ContentController.ARCHIVEDSITE', 'Preview version');
|
|
||||||
$recordLink = Convert::raw2att(Controller::join_links(
|
|
||||||
$this->record->AbsoluteLink(),
|
|
||||||
'?archiveDate=' . urlencode($this->record->LastEdited ?? '')
|
|
||||||
));
|
|
||||||
return "<a class=\"{$linkClass}\" href=\"$recordLink\" target=\"_blank\">$linkTitle</a>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return _t('SilverStripe\\CMS\\Controllers\\SilverStripeNavigator.ARCHIVED', 'Archived');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessage()
|
|
||||||
{
|
|
||||||
$date = Versioned::current_archived_date();
|
|
||||||
if (empty($date)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
/** @var DBDatetime $dateObj */
|
|
||||||
$dateObj = DBField::create_field('Datetime', $date);
|
|
||||||
$title = _t('SilverStripe\\CMS\\Controllers\\ContentController.NOTEWONTBESHOWN', 'Note: this message will not be shown to your visitors');
|
|
||||||
return "<div id=\"SilverStripeNavigatorMessage\" title=\"{$title}\">"
|
|
||||||
. _t('SilverStripe\\CMS\\Controllers\\ContentController.ARCHIVEDSITEFROM', 'Archived site from')
|
|
||||||
. "<br />" . $dateObj->Nice() . "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLink()
|
|
||||||
{
|
|
||||||
$link = $this->record->PreviewLink();
|
|
||||||
return $link ? Controller::join_links($link, '?archiveDate=' . urlencode($this->record->LastEdited ?? '')) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canView($member = null)
|
|
||||||
{
|
|
||||||
/** @var Versioned|DataObject $record */
|
|
||||||
$record = $this->record;
|
|
||||||
return (
|
|
||||||
$record->hasExtension(Versioned::class)
|
|
||||||
&& $record->hasStages()
|
|
||||||
&& $this->isArchived()
|
|
||||||
// Don't follow redirects in preview, they break the CMS editing form
|
|
||||||
&& !($record instanceof RedirectorPage)
|
|
||||||
&& $this->getLink()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isActive()
|
|
||||||
{
|
|
||||||
return $this->isArchived();
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,7 @@
|
|||||||
namespace SilverStripe\CMS\Controllers;
|
namespace SilverStripe\CMS\Controllers;
|
||||||
|
|
||||||
use SilverStripe\Admin\LeftAndMain;
|
use SilverStripe\Admin\LeftAndMain;
|
||||||
|
use SilverStripe\Admin\Navigator\SilverStripeNavigatorItem;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
|
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Core\Config\Config;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class will be moved from `silverstripe/cms` to `silverstripe/admin`.
|
|
||||||
* @deprecated 4.13.0 Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_LiveLink
|
|
||||||
*/
|
|
||||||
class SilverStripeNavigatorItem_LiveLink extends SilverStripeNavigatorItem
|
|
||||||
{
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_LiveLink',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
});
|
|
||||||
parent::__construct($record);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @config */
|
|
||||||
private static $priority = 30;
|
|
||||||
|
|
||||||
public function getHTML()
|
|
||||||
{
|
|
||||||
$livePage = $this->getLivePage();
|
|
||||||
if (!$livePage) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$linkClass = $this->isActive() ? 'class="current" ' : '';
|
|
||||||
$linkTitle = _t('SilverStripe\\CMS\\Controllers\\ContentController.PUBLISHEDSITE', 'Published Site');
|
|
||||||
$recordLink = Convert::raw2att(Controller::join_links($livePage->AbsoluteLink(), "?stage=Live"));
|
|
||||||
return "<a {$linkClass} href=\"$recordLink\">$linkTitle</a>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.PUBLISHED',
|
|
||||||
'Published',
|
|
||||||
'Used for the Switch between draft and published view mode. Needs to be a short label'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessage()
|
|
||||||
{
|
|
||||||
return "<div id=\"SilverStripeNavigatorMessage\" title=\"" . _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.NOTEWONTBESHOWN',
|
|
||||||
'Note: this message will not be shown to your visitors'
|
|
||||||
) . "\">" . _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.PUBLISHEDSITE',
|
|
||||||
'Published Site'
|
|
||||||
) . "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLink()
|
|
||||||
{
|
|
||||||
$link = $this->getLivePage()->PreviewLink();
|
|
||||||
return $link ? Controller::join_links($link, '?stage=Live') : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canView($member = null)
|
|
||||||
{
|
|
||||||
/** @var Versioned|DataObject $record */
|
|
||||||
$record = $this->record;
|
|
||||||
return (
|
|
||||||
$record->hasExtension(Versioned::class)
|
|
||||||
&& $this->showLiveLink()
|
|
||||||
&& $record->hasStages()
|
|
||||||
&& $this->getLivePage()
|
|
||||||
&& $this->getLink()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function showLiveLink()
|
|
||||||
{
|
|
||||||
return (bool)Config::inst()->get(get_class($this->record), 'show_live_link');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isActive()
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
(!Versioned::get_stage() || Versioned::get_stage() == 'Live')
|
|
||||||
&& !$this->isArchived()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getLivePage()
|
|
||||||
{
|
|
||||||
$baseClass = $this->record->baseClass();
|
|
||||||
return Versioned::get_by_stage($baseClass, Versioned::LIVE)->byID($this->record->ID);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Core\Config\Config;
|
|
||||||
use SilverStripe\Core\ClassInfo;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
use SiteTreeFutureState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class will be moved from `silverstripe/cms` to `silverstripe/admin`.
|
|
||||||
* @deprecated 4.13.0 Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_StageLink
|
|
||||||
*/
|
|
||||||
class SilverStripeNavigatorItem_StageLink extends SilverStripeNavigatorItem
|
|
||||||
{
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\VersionedAdmin\Navigator\SilverStripeNavigatorItem_StageLink',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
});
|
|
||||||
parent::__construct($record);
|
|
||||||
}
|
|
||||||
/** @config */
|
|
||||||
private static $priority = 20;
|
|
||||||
|
|
||||||
public function getHTML()
|
|
||||||
{
|
|
||||||
$draftPage = $this->getDraftPage();
|
|
||||||
if (!$draftPage) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$linkClass = $this->isActive() ? 'class="current" ' : '';
|
|
||||||
$linkTitle = _t('SilverStripe\\CMS\\Controllers\\ContentController.DRAFTSITE', 'Draft Site');
|
|
||||||
$recordLink = Convert::raw2att(Controller::join_links($draftPage->AbsoluteLink(), "?stage=Stage"));
|
|
||||||
return "<a {$linkClass} href=\"$recordLink\">$linkTitle</a>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.DRAFT',
|
|
||||||
'Draft',
|
|
||||||
'Used for the Switch between draft and published view mode. Needs to be a short label'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessage()
|
|
||||||
{
|
|
||||||
return "<div id=\"SilverStripeNavigatorMessage\" title=\"" . _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.NOTEWONTBESHOWN',
|
|
||||||
'Note: this message will not be shown to your visitors'
|
|
||||||
) . "\">" . _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.DRAFTSITE',
|
|
||||||
'Draft Site'
|
|
||||||
) . "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLink()
|
|
||||||
{
|
|
||||||
$date = Versioned::current_archived_date();
|
|
||||||
$link = $this->record->PreviewLink();
|
|
||||||
if (!$link) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return Controller::join_links(
|
|
||||||
$link,
|
|
||||||
'?stage=Stage',
|
|
||||||
$date ? '?archiveDate=' . $date : null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canView($member = null)
|
|
||||||
{
|
|
||||||
/** @var Versioned|DataObject $record */
|
|
||||||
$record = $this->record;
|
|
||||||
return (
|
|
||||||
$record->hasExtension(Versioned::class)
|
|
||||||
&& $this->showStageLink()
|
|
||||||
&& $record->hasStages()
|
|
||||||
&& $this->getDraftPage()
|
|
||||||
&& $this->getLink()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function showStageLink()
|
|
||||||
{
|
|
||||||
return (bool)Config::inst()->get(get_class($this->record), 'show_stage_link');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isActive()
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
Versioned::get_stage() == 'Stage'
|
|
||||||
&& !(ClassInfo::exists('SiteTreeFutureState') && SiteTreeFutureState::get_future_datetime())
|
|
||||||
&& !$this->isArchived()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getDraftPage()
|
|
||||||
{
|
|
||||||
$baseClass = $this->record->baseClass();
|
|
||||||
return Versioned::get_by_stage($baseClass, Versioned::DRAFT)->byID($this->record->ID);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem;
|
|
||||||
use SilverStripe\Core\Config\Config;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\Security\Member;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class will be moved from `silverstripe/cms` to `silverstripe/admin`.
|
|
||||||
* @deprecated 4.13.0 Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigatorItem_Unversioned
|
|
||||||
*/
|
|
||||||
class SilverStripeNavigatorItem_Unversioned extends SilverStripeNavigatorItem
|
|
||||||
{
|
|
||||||
public function __construct(CMSPreviewable $record)
|
|
||||||
{
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be renamed SilverStripe\Admin\Navigator\SilverStripeNavigatorItem_Unversioned',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
});
|
|
||||||
parent::__construct($record);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHTML()
|
|
||||||
{
|
|
||||||
$recordLink = Convert::raw2att($this->getLink());
|
|
||||||
$linkTitle = _t('SilverStripe\\CMS\\Controllers\\ContentController.UNVERSIONEDPREVIEW', 'Preview');
|
|
||||||
return "<a class=\"current\" href=\"$recordLink\">$linkTitle</a>";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLink()
|
|
||||||
{
|
|
||||||
return $this->getRecord()->PreviewLink() ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return _t(
|
|
||||||
'SilverStripe\\CMS\\Controllers\\ContentController.UNVERSIONEDPREVIEW',
|
|
||||||
'Preview',
|
|
||||||
'Used for the Switch between states (if any other other states are added). Needs to be a short label'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the record doesn't have the Versioned extension and is configured to display this item.
|
|
||||||
*
|
|
||||||
* @param Member $member
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function canView($member = null)
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
$this->recordIsUnversioned()
|
|
||||||
&& $this->showUnversionedLink()
|
|
||||||
&& $this->getLink()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function recordIsUnversioned(): bool
|
|
||||||
{
|
|
||||||
$record = $this->getRecord();
|
|
||||||
// If the record has the Versioned extension, it can be considered unversioned
|
|
||||||
// for the purposes of this class if it has no stages and is not archived.
|
|
||||||
if ($record->hasExtension(Versioned::class)) {
|
|
||||||
return (!$record->hasStages()) && !$this->isArchived();
|
|
||||||
}
|
|
||||||
// Completely unversioned.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the record is configured to display this item.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function showUnversionedLink(): bool
|
|
||||||
{
|
|
||||||
return (bool) Config::inst()->get(get_class($this->record), 'show_unversioned_preview_link');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This item is always active, as there are unlikely to be other preview states available for the record.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isActive()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -134,7 +134,7 @@ class SiteTreeURLSegmentField extends TextField
|
|||||||
*/
|
*/
|
||||||
public function getURLPrefix()
|
public function getURLPrefix()
|
||||||
{
|
{
|
||||||
return $this->urlPrefix;
|
return rtrim($this->urlPrefix ?? '', '/') . '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getURLSuffix()
|
public function getURLSuffix()
|
||||||
|
@ -25,7 +25,6 @@ use SilverStripe\Core\Manifest\ModuleResource;
|
|||||||
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
||||||
use SilverStripe\Core\Manifest\VersionProvider;
|
use SilverStripe\Core\Manifest\VersionProvider;
|
||||||
use SilverStripe\Core\Resettable;
|
use SilverStripe\Core\Resettable;
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Forms\CheckboxField;
|
use SilverStripe\Forms\CheckboxField;
|
||||||
use SilverStripe\Forms\CompositeField;
|
use SilverStripe\Forms\CompositeField;
|
||||||
use SilverStripe\Forms\DropdownField;
|
use SilverStripe\Forms\DropdownField;
|
||||||
@ -639,7 +638,7 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
if ($this->hasMethod('alternateAbsoluteLink')) {
|
if ($this->hasMethod('alternateAbsoluteLink')) {
|
||||||
return $this->alternateAbsoluteLink($action);
|
return $this->alternateAbsoluteLink($action);
|
||||||
} else {
|
} else {
|
||||||
return Director::absoluteURL($this->Link($action));
|
return Director::absoluteURL((string) $this->Link($action));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,13 +651,6 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
*/
|
*/
|
||||||
public function PreviewLink($action = null)
|
public function PreviewLink($action = null)
|
||||||
{
|
{
|
||||||
if ($this->hasMethod('alternatePreviewLink')) {
|
|
||||||
Deprecation::withNoReplacement(function () use ($action) {
|
|
||||||
Deprecation::notice('5.0', 'Use updatePreviewLink or override PreviewLink method');
|
|
||||||
return $this->alternatePreviewLink($action);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$link = $this->AbsoluteLink($action);
|
$link = $this->AbsoluteLink($action);
|
||||||
$this->extend('updatePreviewLink', $link, $action);
|
$this->extend('updatePreviewLink', $link, $action);
|
||||||
return $link;
|
return $link;
|
||||||
@ -699,15 +691,17 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
$base = $this->URLSegment;
|
$base = $this->URLSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->extend('updateRelativeLink', $base, $action);
|
|
||||||
|
|
||||||
// Legacy support: If $action === true, retain URLSegment for homepages,
|
// Legacy support: If $action === true, retain URLSegment for homepages,
|
||||||
// but don't append any action
|
// but don't append any action
|
||||||
if ($action === true) {
|
if ($action === true) {
|
||||||
$action = null;
|
$action = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Controller::join_links($base, '/', $action);
|
$link = Controller::join_links($base, $action);
|
||||||
|
|
||||||
|
$this->extend('updateRelativeLink', $link, $base, $action);
|
||||||
|
|
||||||
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2466,7 +2460,6 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
// "readonly"/viewing version that isn't the current version of the record
|
// "readonly"/viewing version that isn't the current version of the record
|
||||||
/** @var SiteTree $stageRecord */
|
/** @var SiteTree $stageRecord */
|
||||||
$stageRecord = Versioned::get_by_stage(static::class, Versioned::DRAFT)->byID($this->ID);
|
$stageRecord = Versioned::get_by_stage(static::class, Versioned::DRAFT)->byID($this->ID);
|
||||||
/** @skipUpgrade */
|
|
||||||
if ($stageRecord && $stageRecord->Version != $this->Version) {
|
if ($stageRecord && $stageRecord->Version != $this->Version) {
|
||||||
$moreOptions->push(FormAction::create('email', _t('SilverStripe\\CMS\\Controllers\\CMSMain.EMAIL', 'Email')));
|
$moreOptions->push(FormAction::create('email', _t('SilverStripe\\CMS\\Controllers\\CMSMain.EMAIL', 'Email')));
|
||||||
$moreOptions->push(FormAction::create('rollback', _t('SilverStripe\\CMS\\Controllers\\CMSMain.ROLLBACK', 'Roll back to this version')));
|
$moreOptions->push(FormAction::create('rollback', _t('SilverStripe\\CMS\\Controllers\\CMSMain.ROLLBACK', 'Roll back to this version')));
|
||||||
@ -2511,7 +2504,7 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
// Note: It would be nice to have a canRestore() permission at some point
|
// Note: It would be nice to have a canRestore() permission at some point
|
||||||
if ($canEdit && !$isOnDraft && !$isPublished) {
|
if ($canEdit && !$isOnDraft && !$isPublished) {
|
||||||
// Determine if we should force a restore to root (where once it was a subpage)
|
// Determine if we should force a restore to root (where once it was a subpage)
|
||||||
$restoreToRoot = $this->isParentArchived();
|
$restoreToRoot = $this->isParentArchived() && $this->config()->get('can_be_root');
|
||||||
|
|
||||||
// "restore"
|
// "restore"
|
||||||
$title = $restoreToRoot
|
$title = $restoreToRoot
|
||||||
@ -2520,13 +2513,15 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
$description = $restoreToRoot
|
$description = $restoreToRoot
|
||||||
? _t('SilverStripe\\CMS\\Controllers\\CMSMain.RESTORE_TO_ROOT_DESC', 'Restore the archived version to draft as a top level page')
|
? _t('SilverStripe\\CMS\\Controllers\\CMSMain.RESTORE_TO_ROOT_DESC', 'Restore the archived version to draft as a top level page')
|
||||||
: _t('SilverStripe\\CMS\\Controllers\\CMSMain.RESTORE_DESC', 'Restore the archived version to draft');
|
: _t('SilverStripe\\CMS\\Controllers\\CMSMain.RESTORE_DESC', 'Restore the archived version to draft');
|
||||||
$majorActions->push(
|
if (!$this->isParentArchived() || $restoreToRoot) {
|
||||||
FormAction::create('restore', $title)
|
$majorActions->push(
|
||||||
->setDescription($description)
|
FormAction::create('restore', $title)
|
||||||
->setAttribute('data-to-root', $restoreToRoot)
|
->setDescription($description)
|
||||||
->addExtraClass('btn-warning font-icon-back-in-time')
|
->setAttribute('data-to-root', $restoreToRoot)
|
||||||
->setUseButtonTag(true)
|
->addExtraClass('btn-warning font-icon-back-in-time')
|
||||||
);
|
->setUseButtonTag(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a page is on any stage it can be archived
|
// If a page is on any stage it can be archived
|
||||||
@ -2786,35 +2781,6 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
return $allowedChildren;
|
return $allowedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.12.0 Use creatableChildPages() instead
|
|
||||||
*
|
|
||||||
* Gets a list of the page types that can be created under this specific page
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function creatableChildren()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.12.0', 'Use creatableChildPages() instead');
|
|
||||||
// Build the list of candidate children
|
|
||||||
$cache = SiteTree::singleton()->getCreatableChildrenCache();
|
|
||||||
$cacheKey = $this->generateChildrenCacheKey(Security::getCurrentUser() ? Security::getCurrentUser()->ID : 0);
|
|
||||||
$children = $cache->get($cacheKey, []);
|
|
||||||
if (!$children || !isset($children[$this->ID])) {
|
|
||||||
$children[$this->ID] = [];
|
|
||||||
$candidates = static::page_type_classes();
|
|
||||||
foreach ($candidates as $childClass) {
|
|
||||||
$child = singleton($childClass);
|
|
||||||
if ($child->canCreate(null, ['Parent' => $this])) {
|
|
||||||
$children[$this->ID][$childClass] = $child->i18n_singular_name();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$cache->set($cacheKey, $children);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $children[$this->ID];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Gets a list of the page types that can be created under this specific page, including font icons
|
* Gets a list of the page types that can be created under this specific page, including font icons
|
||||||
@ -3063,14 +3029,6 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
// If we have a class of "{$ClassName}Controller" then we found our controller
|
// If we have a class of "{$ClassName}Controller" then we found our controller
|
||||||
if (class_exists($candidate = sprintf('%sController', $class))) {
|
if (class_exists($candidate = sprintf('%sController', $class))) {
|
||||||
return $candidate;
|
return $candidate;
|
||||||
} elseif (class_exists($candidate = sprintf('%s_Controller', $class))) {
|
|
||||||
// Support the legacy underscored filename, but raise a deprecation notice
|
|
||||||
Deprecation::notice(
|
|
||||||
'5.0',
|
|
||||||
'Underscored controller class names are deprecated. Use "MyController" instead of "My_Controller".',
|
|
||||||
Deprecation::SCOPE_GLOBAL
|
|
||||||
);
|
|
||||||
return $candidate;
|
|
||||||
} elseif (is_array($namespaceMap)) {
|
} elseif (is_array($namespaceMap)) {
|
||||||
foreach ($namespaceMap as $pageNamespace => $controllerNamespace) {
|
foreach ($namespaceMap as $pageNamespace => $controllerNamespace) {
|
||||||
if (strpos($class, $pageNamespace) !== 0) {
|
if (strpos($class, $pageNamespace) !== 0) {
|
||||||
@ -3334,7 +3292,7 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache key for creatableChildren() method
|
* Cache key for creatableChildPages() method
|
||||||
*
|
*
|
||||||
* @param int $memberID
|
* @param int $memberID
|
||||||
* @return string
|
* @return string
|
||||||
|
@ -75,13 +75,15 @@ abstract class SiteTreeExtension extends DataExtension
|
|||||||
* before {@link SiteTree::RelativeLink()} calls {@link Controller::join_links()}
|
* before {@link SiteTree::RelativeLink()} calls {@link Controller::join_links()}
|
||||||
* on the $base and $action
|
* on the $base and $action
|
||||||
*
|
*
|
||||||
* @param string &$base The URL of this page relative to siteroot, not including
|
* @param string &$link The URL of this page relative to siteroot including
|
||||||
* the action
|
* the action
|
||||||
* @param string|boolean &$action The action or subpage called on this page.
|
* @param string $base The URL of this page relative to siteroot, not including
|
||||||
|
* the action
|
||||||
|
* @param string|boolean $action The action or subpage called on this page.
|
||||||
* (Legacy support) If this is true, then do not reduce the 'home' urlsegment
|
* (Legacy support) If this is true, then do not reduce the 'home' urlsegment
|
||||||
* to an empty link
|
* to an empty link
|
||||||
*/
|
*/
|
||||||
public function updateRelativeLink(&$base, &$action)
|
public function updateRelativeLink(&$link, $base, $action)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Model;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Assets\File;
|
|
||||||
use SilverStripe\ORM\DataExtension;
|
|
||||||
use SilverStripe\View\SSViewer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.2.0 Use FileLinkTracking instead
|
|
||||||
* @property File $owner
|
|
||||||
*/
|
|
||||||
class SiteTreeFileExtension extends DataExtension
|
|
||||||
{
|
|
||||||
private static $casting = [
|
|
||||||
'BackLinkHTMLList' => 'HTMLFragment'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate an HTML list which provides links to where a file is used.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.2.0', 'Use FileLinkTracking instead', Deprecation::SCOPE_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function BackLinkHTMLList()
|
|
||||||
{
|
|
||||||
$viewer = SSViewer::create(['type' => 'Includes', self::class . '_description']);
|
|
||||||
return $viewer->process($this->owner);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Model;
|
|
||||||
|
|
||||||
use SilverStripe\Assets\File;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Forms\FieldList;
|
|
||||||
use SilverStripe\Forms\Tab;
|
|
||||||
use SilverStripe\Forms\TabSet;
|
|
||||||
use SilverStripe\ORM\DataExtension;
|
|
||||||
use SilverStripe\Admin\Forms\UsedOnTable;
|
|
||||||
use SilverStripe\Versioned\RecursivePublishable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.12.0 Use UsedOnTable instead
|
|
||||||
*
|
|
||||||
* Extension applied to {@see FileFormFactory} to decorate with a "Used on:" information area.
|
|
||||||
* Uses tracking provided by {@see SiteTreeFileExtension} to generate this.
|
|
||||||
*
|
|
||||||
* @property File $owner
|
|
||||||
* @deprecated 4.12.0 Use UsedOnTable instead
|
|
||||||
*/
|
|
||||||
class SiteTreeFileFormFactoryExtension extends DataExtension
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.12.0', 'Use UsedOnTable instead', Deprecation::SCOPE_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.12.0 Use UsedOnTable instead
|
|
||||||
*/
|
|
||||||
public function updateFormFields(FieldList $fields, $controller, $formName, $context)
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.12.0', 'Use UsedOnTable instead');
|
|
||||||
/** @var TabSet $tabset */
|
|
||||||
$tabset = $fields->fieldByName('Editor');
|
|
||||||
if (!$tabset) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$usedOnField = UsedOnTable::create('UsedOnTableReplacement');
|
|
||||||
$usedOnField->setRecord($context['Record']);
|
|
||||||
|
|
||||||
// Add field to new tab
|
|
||||||
/** @var Tab $tab */
|
|
||||||
$tab = Tab::create('Usage', _t(__CLASS__ . '.USAGE', 'Usage'), $usedOnField);
|
|
||||||
$tabset->push($tab);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Model;
|
|
||||||
|
|
||||||
use SilverStripe\Assets\File;
|
|
||||||
use SilverStripe\Assets\Folder;
|
|
||||||
use SilverStripe\Assets\Shortcodes\FileLink;
|
|
||||||
use SilverStripe\Core\ClassInfo;
|
|
||||||
use SilverStripe\Core\Config\Config;
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\ArrayList;
|
|
||||||
use SilverStripe\ORM\DataExtension;
|
|
||||||
use SilverStripe\ORM\DataList;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.2.0 Will be removed without equivalent functionality to replace it
|
|
||||||
*/
|
|
||||||
class SiteTreeFolderExtension extends DataExtension
|
|
||||||
{
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.2.0', 'Will be removed without equivalent functionality to replace it', Deprecation::SCOPE_CLASS);
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks for files used in system and create where clause which contains all ID's of files.
|
|
||||||
*
|
|
||||||
* @deprecated 4.2.0 Will be removed without equivalent functionality to replace it
|
|
||||||
* @returns string where clause which will work as filter.
|
|
||||||
*/
|
|
||||||
public function getUnusedFilesListFilter()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.2.0', 'Will be removed without equivalent functionality to replace it');
|
|
||||||
|
|
||||||
// Add all records in link tracking
|
|
||||||
$usedFiles = FileLink::get()->column('LinkedID');
|
|
||||||
|
|
||||||
// Get all classes that aren't folder
|
|
||||||
$fileClasses = array_diff_key(
|
|
||||||
ClassInfo::subclassesFor(File::class) ?? [],
|
|
||||||
ClassInfo::subclassesFor(Folder::class)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Search on a class-by-class basis
|
|
||||||
$classes = ClassInfo::subclassesFor(SiteTree::class);
|
|
||||||
|
|
||||||
$schema = DataObject::getSchema();
|
|
||||||
foreach ($classes as $className) {
|
|
||||||
// Build query based on all direct has_ones on this class
|
|
||||||
$hasOnes = Config::inst()->get($className, 'has_one', Config::UNINHERITED);
|
|
||||||
if (empty($hasOnes)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$where = [];
|
|
||||||
$columns = [];
|
|
||||||
foreach ($hasOnes as $relName => $joinClass) {
|
|
||||||
if (in_array($joinClass, $fileClasses ?? [])) {
|
|
||||||
$column = $relName . 'ID';
|
|
||||||
$columns[] = $column;
|
|
||||||
$quotedColumn = $schema->sqlColumnForField($className, $column);
|
|
||||||
$where[] = "{$quotedColumn} > 0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all records with any file ID in the searched columns
|
|
||||||
$recordsArray = DataList::create($className)->whereAny($where)->toArray();
|
|
||||||
$records = ArrayList::create($recordsArray);
|
|
||||||
foreach ($columns as $column) {
|
|
||||||
$usedFiles = array_unique(array_merge($usedFiles, $records->column($column)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create filter based on class and id
|
|
||||||
$classFilter = sprintf(
|
|
||||||
"(\"File\".\"ClassName\" IN (%s))",
|
|
||||||
implode(", ", Convert::raw2sql($fileClasses, true))
|
|
||||||
);
|
|
||||||
if ($usedFiles) {
|
|
||||||
return "\"File\".\"ID\" NOT IN (" . implode(', ', $usedFiles) . ") AND $classFilter";
|
|
||||||
} else {
|
|
||||||
return $classFilter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,8 +9,6 @@ use SilverStripe\ORM\DataObject;
|
|||||||
*
|
*
|
||||||
* @method DataObject Parent() Parent object
|
* @method DataObject Parent() Parent object
|
||||||
* @method SiteTree Linked() Page being linked to
|
* @method SiteTree Linked() Page being linked to
|
||||||
*
|
|
||||||
* Run `MigrateSiteTreeLinkingTask` to migrate from old table to this.
|
|
||||||
*/
|
*/
|
||||||
class SiteTreeLink extends DataObject
|
class SiteTreeLink extends DataObject
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@ namespace SilverStripe\CMS\Model;
|
|||||||
|
|
||||||
use Page;
|
use Page;
|
||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
use SilverStripe\Forms\LiteralField;
|
use SilverStripe\Forms\LiteralField;
|
||||||
use SilverStripe\Forms\ReadonlyTransformation;
|
use SilverStripe\Forms\ReadonlyTransformation;
|
||||||
@ -360,30 +359,6 @@ class VirtualPage extends Page
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.2.0 Will be removed without equivalent functionality to replace it
|
|
||||||
*/
|
|
||||||
public function updateImageTracking()
|
|
||||||
{
|
|
||||||
Deprecation::notice('4.2.0', 'Will be removed without equivalent functionality to replace it');
|
|
||||||
|
|
||||||
// Doesn't work on unsaved records
|
|
||||||
if (!$this->isInDB()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove CopyContentFrom() from the cache
|
|
||||||
unset($this->components['CopyContentFrom']);
|
|
||||||
|
|
||||||
// Update ImageTracking
|
|
||||||
$copyContentFrom = $this->CopyContentFrom();
|
|
||||||
if (!$copyContentFrom || !$copyContentFrom->isInDB()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->FileTracking()->setByIDList($copyContentFrom->FileTracking()->column('ID'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CMSTreeClasses()
|
public function CMSTreeClasses()
|
||||||
{
|
{
|
||||||
$parentClass = sprintf(
|
$parentClass = sprintf(
|
||||||
|
@ -31,7 +31,7 @@ class RecentlyEditedReport extends Report
|
|||||||
$threshold = strtotime('-14 days', DBDatetime::now()->getTimestamp());
|
$threshold = strtotime('-14 days', DBDatetime::now()->getTimestamp());
|
||||||
return SiteTree::get()
|
return SiteTree::get()
|
||||||
->filter('LastEdited:GreaterThan', date("Y-m-d H:i:s", $threshold))
|
->filter('LastEdited:GreaterThan', date("Y-m-d H:i:s", $threshold))
|
||||||
->sort("\"$tableName\".\"LastEdited\" DESC");
|
->orderBy("\"$tableName\".\"LastEdited\" DESC");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function columns()
|
public function columns()
|
||||||
|
@ -39,7 +39,6 @@ class ContentControllerSearchExtension extends Extension
|
|||||||
$actions = FieldList::create(
|
$actions = FieldList::create(
|
||||||
FormAction::create('results', _t('SilverStripe\\CMS\\Search\\SearchForm.GO', 'Go'))
|
FormAction::create('results', _t('SilverStripe\\CMS\\Search\\SearchForm.GO', 'Go'))
|
||||||
);
|
);
|
||||||
/** @skipUpgrade */
|
|
||||||
$form = SearchForm::create($this->owner, 'SearchForm', $fields, $actions);
|
$form = SearchForm::create($this->owner, 'SearchForm', $fields, $actions);
|
||||||
$form->classesToSearch(FulltextSearchable::get_searchable_classes());
|
$form->classesToSearch(FulltextSearchable::get_searchable_classes());
|
||||||
return $form;
|
return $form;
|
||||||
|
@ -13,17 +13,11 @@ use SilverStripe\Forms\HiddenField;
|
|||||||
use SilverStripe\Forms\TextField;
|
use SilverStripe\Forms\TextField;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\SS_List;
|
use SilverStripe\ORM\SS_List;
|
||||||
use Translatable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard basic search form which conducts a fulltext search on all {@link SiteTree}
|
* Standard basic search form which conducts a fulltext search on all {@link SiteTree}
|
||||||
* objects.
|
* objects.
|
||||||
*
|
*
|
||||||
* If multilingual content is enabled through the {@link Translatable} extension,
|
|
||||||
* only pages the currently set language on the holder for this searchform are found.
|
|
||||||
* The language is set through a hidden field in the form, which is prepoluated
|
|
||||||
* with {@link Translatable::get_current_locale()} when then form is constructed.
|
|
||||||
*
|
|
||||||
* @see Use ModelController and SearchContext for a more generic search implementation based around DataObject
|
* @see Use ModelController and SearchContext for a more generic search implementation based around DataObject
|
||||||
*/
|
*/
|
||||||
class SearchForm extends Form
|
class SearchForm extends Form
|
||||||
@ -51,7 +45,6 @@ class SearchForm extends Form
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @skipUpgrade
|
|
||||||
* @param RequestHandler $controller
|
* @param RequestHandler $controller
|
||||||
* @param string $name The name of the form (used in URL addressing)
|
* @param string $name The name of the form (used in URL addressing)
|
||||||
* @param FieldList $fields Optional, defaults to a single field named "Search". Search logic needs to be customized
|
* @param FieldList $fields Optional, defaults to a single field named "Search". Search logic needs to be customized
|
||||||
@ -70,12 +63,6 @@ class SearchForm extends Form
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (class_exists('Translatable')
|
|
||||||
&& SiteTree::singleton()->hasExtension('Translatable')
|
|
||||||
) {
|
|
||||||
$fields->push(new HiddenField('searchlocale', 'searchlocale', Translatable::get_current_locale()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$actions) {
|
if (!$actions) {
|
||||||
$actions = new FieldList(
|
$actions = new FieldList(
|
||||||
new FormAction("results", _t(__CLASS__.'.GO', 'Go'))
|
new FormAction("results", _t(__CLASS__.'.GO', 'Go'))
|
||||||
@ -130,22 +117,6 @@ class SearchForm extends Form
|
|||||||
// Get request data from request handler
|
// Get request data from request handler
|
||||||
$request = $this->getRequestHandler()->getRequest();
|
$request = $this->getRequestHandler()->getRequest();
|
||||||
|
|
||||||
// set language (if present)
|
|
||||||
$locale = null;
|
|
||||||
$origLocale = null;
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
$locale = $request->requestVar('searchlocale');
|
|
||||||
if (SiteTree::singleton()->hasExtension('Translatable') && $locale) {
|
|
||||||
if ($locale === "ALL") {
|
|
||||||
Translatable::disable_locale_filter();
|
|
||||||
} else {
|
|
||||||
$origLocale = Translatable::get_current_locale();
|
|
||||||
|
|
||||||
Translatable::set_current_locale($locale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$keywords = $request->requestVar('Search');
|
$keywords = $request->requestVar('Search');
|
||||||
|
|
||||||
$andProcessor = function ($matches) {
|
$andProcessor = function ($matches) {
|
||||||
@ -181,17 +152,6 @@ class SearchForm extends Form
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset locale
|
|
||||||
if (class_exists('Translatable')) {
|
|
||||||
if (SiteTree::singleton()->hasExtension('Translatable') && $locale) {
|
|
||||||
if ($locale == "ALL") {
|
|
||||||
Translatable::enable_locale_filter();
|
|
||||||
} else {
|
|
||||||
Translatable::set_current_locale($origLocale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tasks;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Dev\BuildTask;
|
|
||||||
use SilverStripe\Dev\Debug;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\ORM\DB;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates legacy SiteTree link tracking into new polymorphic many_many relation.
|
|
||||||
* This should be done for any site upgrading to 4.2.0
|
|
||||||
*
|
|
||||||
* @deprecated 4.13.0 Will be removed without equivalent functionality to replace it
|
|
||||||
*/
|
|
||||||
class MigrateSiteTreeLinkingTask extends BuildTask
|
|
||||||
{
|
|
||||||
private static $segment = 'MigrateSiteTreeLinkingTask';
|
|
||||||
|
|
||||||
protected $title = 'Migrate SiteTree Linking Task';
|
|
||||||
|
|
||||||
protected $description = 'Updates legacy SiteTree link tracking into new polymorphic many_many relation';
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be removed without equivalent functionality to replace it',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run($request)
|
|
||||||
{
|
|
||||||
// Ensure legacy table exists
|
|
||||||
$exists = DB::get_conn()->getSchemaManager()->hasTable('SiteTree_LinkTracking');
|
|
||||||
if (!$exists) {
|
|
||||||
DB::alteration_message("Table SiteTree_LinkTracking has already been migrated, or doesn't exist");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pages = 0;
|
|
||||||
|
|
||||||
// Ensure sync occurs on draft
|
|
||||||
Versioned::withVersionedMode(function () use (&$pages) {
|
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
|
||||||
|
|
||||||
$sitetreeTbl = DataObject::singleton(SiteTree::class)->baseTable();
|
|
||||||
|
|
||||||
/** @var SiteTree[] $linkedPages */
|
|
||||||
$linkedPages = SiteTree::get()
|
|
||||||
->innerJoin(
|
|
||||||
'SiteTree_LinkTracking',
|
|
||||||
"\"SiteTree_LinkTracking\".\"SiteTreeID\" = \"$sitetreeTbl\".\"ID\""
|
|
||||||
);
|
|
||||||
foreach ($linkedPages as $page) {
|
|
||||||
// Command page to update symlink tracking
|
|
||||||
$page->syncLinkTracking();
|
|
||||||
$pages++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
DB::alteration_message("Migrated page links on " . SiteTree::singleton()->i18n_pluralise($pages));
|
|
||||||
|
|
||||||
// Disable table to prevent double-migration
|
|
||||||
DB::dont_require_table('SiteTree_LinkTracking');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,388 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tasks;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Forms\CheckboxSetField;
|
|
||||||
use SilverStripe\Forms\FieldList;
|
|
||||||
use SilverStripe\Forms\Form;
|
|
||||||
use SilverStripe\Forms\FormAction;
|
|
||||||
use SilverStripe\Forms\HeaderField;
|
|
||||||
use SilverStripe\Forms\LiteralField;
|
|
||||||
use SilverStripe\Forms\OptionsetField;
|
|
||||||
use SilverStripe\ORM\ArrayList;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\ORM\SS_List;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
use SilverStripe\Security\Permission;
|
|
||||||
use SilverStripe\Security\Security;
|
|
||||||
use SilverStripe\View\Requirements;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Identify "orphaned" pages which point to a parent
|
|
||||||
* that no longer exists in a specific stage.
|
|
||||||
* Shows the pages to an administrator, who can then
|
|
||||||
* decide which pages to remove by ticking a checkbox
|
|
||||||
* and manually executing the removal.
|
|
||||||
*
|
|
||||||
* Caution: Pages also count as orphans if they don't
|
|
||||||
* have parents in this stage, even if the parent has a representation
|
|
||||||
* in the other stage:
|
|
||||||
* - A live child is orphaned if its parent was deleted from live, but still exists on stage
|
|
||||||
* - A stage child is orphaned if its parent was deleted from stage, but still exists on live
|
|
||||||
*
|
|
||||||
* See {@link RemoveOrphanedPagesTaskTest} for an example sitetree
|
|
||||||
* before and after orphan removal.
|
|
||||||
*
|
|
||||||
* @author Ingo Schommer (<firstname>@silverstripe.com), SilverStripe Ltd.
|
|
||||||
*
|
|
||||||
* @deprecated 4.13.0 Will be removed without equivalent functionality to replace it
|
|
||||||
*/
|
|
||||||
class RemoveOrphanedPagesTask extends Controller
|
|
||||||
{
|
|
||||||
|
|
||||||
private static $allowed_actions = [
|
|
||||||
'index' => 'ADMIN',
|
|
||||||
'Form' => 'ADMIN',
|
|
||||||
'run' => 'ADMIN',
|
|
||||||
'handleAction' => 'ADMIN',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $title = 'Removed orphaned pages without existing parents from both stage and live';
|
|
||||||
|
|
||||||
protected $description = "
|
|
||||||
<p>
|
|
||||||
Identify 'orphaned' pages which point to a parent
|
|
||||||
that no longer exists in a specific stage.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Caution: Pages also count as orphans if they don't
|
|
||||||
have parents in this stage, even if the parent has a representation
|
|
||||||
in the other stage:<br />
|
|
||||||
- A live child is orphaned if its parent was deleted from live, but still exists on stage<br />
|
|
||||||
- A stage child is orphaned if its parent was deleted from stage, but still exists on live
|
|
||||||
</p>
|
|
||||||
";
|
|
||||||
|
|
||||||
protected $orphanedSearchClass = SiteTree::class;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be removed without equivalent functionality to replace it',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function init()
|
|
||||||
{
|
|
||||||
parent::init();
|
|
||||||
|
|
||||||
if (!Permission::check('ADMIN')) {
|
|
||||||
Security::permissionFailure($this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Link($action = null)
|
|
||||||
{
|
|
||||||
/** @skipUpgrade */
|
|
||||||
return Controller::join_links('RemoveOrphanedPagesTask', $action, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
Requirements::javascript('http://code.jquery.com/jquery-1.7.2.min.js');
|
|
||||||
Requirements::customCSS('#OrphanIDs .middleColumn {width: auto;}');
|
|
||||||
Requirements::customCSS('#OrphanIDs label {display: inline;}');
|
|
||||||
|
|
||||||
return $this->renderWith('BlankPage');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Form()
|
|
||||||
{
|
|
||||||
$fields = new FieldList();
|
|
||||||
$source = [];
|
|
||||||
|
|
||||||
$fields->push(new HeaderField(
|
|
||||||
'Header',
|
|
||||||
_t(__CLASS__ . '.HEADER', 'Remove all orphaned pages task')
|
|
||||||
));
|
|
||||||
$fields->push(new LiteralField(
|
|
||||||
'Description',
|
|
||||||
$this->description
|
|
||||||
));
|
|
||||||
|
|
||||||
$orphans = $this->getOrphanedPages($this->orphanedSearchClass);
|
|
||||||
if ($orphans) {
|
|
||||||
foreach ($orphans as $orphan) {
|
|
||||||
/** @var SiteTree $latestVersion */
|
|
||||||
$latestVersion = Versioned::get_latest_version($this->orphanedSearchClass, $orphan->ID);
|
|
||||||
$latestAuthor = DataObject::get_by_id('SilverStripe\\Security\\Member', $latestVersion->AuthorID);
|
|
||||||
$orphanBaseTable = DataObject::getSchema()->baseDataTable($this->orphanedSearchClass);
|
|
||||||
$liveRecord = Versioned::get_one_by_stage(
|
|
||||||
$this->orphanedSearchClass,
|
|
||||||
'Live',
|
|
||||||
["\"$orphanBaseTable\".\"ID\"" => $orphan->ID]
|
|
||||||
);
|
|
||||||
$label = sprintf(
|
|
||||||
'<a href="admin/pages/edit/show/%d">%s</a> <small>(#%d, Last Modified Date: %s, Last Modifier: %s, %s)</small>',
|
|
||||||
$orphan->ID,
|
|
||||||
$orphan->Title,
|
|
||||||
$orphan->ID,
|
|
||||||
$orphan->dbObject('LastEdited')->Nice(),
|
|
||||||
($latestAuthor) ? $latestAuthor->Title : 'unknown',
|
|
||||||
($liveRecord) ? 'is published' : 'not published'
|
|
||||||
);
|
|
||||||
$source[$orphan->ID] = $label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($orphans && $orphans->count()) {
|
|
||||||
$fields->push(new CheckboxSetField('OrphanIDs', false, $source));
|
|
||||||
$fields->push(new LiteralField(
|
|
||||||
'SelectAllLiteral',
|
|
||||||
sprintf(
|
|
||||||
'<p><a href="#" onclick="javascript:jQuery(\'#Form_Form_OrphanIDs :checkbox\').attr(\'checked\', \'checked\'); return false;">%s</a> ',
|
|
||||||
_t(__CLASS__ . '.SELECTALL', 'select all')
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$fields->push(new LiteralField(
|
|
||||||
'UnselectAllLiteral',
|
|
||||||
sprintf(
|
|
||||||
'<a href="#" onclick="javascript:jQuery(\'#Form_Form_OrphanIDs :checkbox\').attr(\'checked\', \'\'); return false;">%s</a></p>',
|
|
||||||
_t(__CLASS__ . '.UNSELECTALL', 'unselect all')
|
|
||||||
)
|
|
||||||
));
|
|
||||||
$fields->push(new OptionsetField(
|
|
||||||
'OrphanOperation',
|
|
||||||
_t('SilverStripe\\CMS\\Tasks\\RemoveOrphanedPagesTask.CHOOSEOPERATION', 'Choose operation:'),
|
|
||||||
[
|
|
||||||
'rebase' => _t(
|
|
||||||
__CLASS__ . '.OPERATION_REBASE',
|
|
||||||
sprintf(
|
|
||||||
'Rebase selected to a new holder page "%s" and unpublish. None of these pages will show up for website visitors.',
|
|
||||||
$this->rebaseHolderTitle()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
'remove' => _t(__CLASS__ . '.OPERATION_REMOVE', 'Remove selected from all stages (WARNING: Will destroy all selected pages from both stage and live)'),
|
|
||||||
],
|
|
||||||
'rebase'
|
|
||||||
));
|
|
||||||
$fields->push(new LiteralField(
|
|
||||||
'Warning',
|
|
||||||
sprintf(
|
|
||||||
'<p class="message">%s</p>',
|
|
||||||
_t(
|
|
||||||
__CLASS__ . '.DELETEWARNING',
|
|
||||||
'Warning: These operations are not reversible. Please handle with care.'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
$fields->push(new LiteralField(
|
|
||||||
'NotFoundLabel',
|
|
||||||
sprintf(
|
|
||||||
'<p class="message">%s</p>',
|
|
||||||
_t(__CLASS__ . '.NONEFOUND', 'No orphans found')
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
$form = new Form(
|
|
||||||
$this,
|
|
||||||
'SilverStripe\\Forms\\Form',
|
|
||||||
$fields,
|
|
||||||
new FieldList(
|
|
||||||
new FormAction('doSubmit', _t(__CLASS__ . '.BUTTONRUN', 'Run'))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$orphans || !$orphans->count()) {
|
|
||||||
$form->makeReadonly();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run($request)
|
|
||||||
{
|
|
||||||
// @todo Merge with BuildTask functionality
|
|
||||||
}
|
|
||||||
|
|
||||||
public function doSubmit($data, $form)
|
|
||||||
{
|
|
||||||
set_time_limit(60*10); // 10 minutes
|
|
||||||
|
|
||||||
if (!isset($data['OrphanIDs']) || !isset($data['OrphanOperation'])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$successIDs = null;
|
|
||||||
switch ($data['OrphanOperation']) {
|
|
||||||
case 'remove':
|
|
||||||
$successIDs = $this->removeOrphans($data['OrphanIDs']);
|
|
||||||
break;
|
|
||||||
case 'rebase':
|
|
||||||
$successIDs = $this->rebaseOrphans($data['OrphanIDs']);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new \InvalidArgumentException(sprintf("Unknown operation: '%s'", $data['OrphanOperation']));
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = '';
|
|
||||||
if ($successIDs) {
|
|
||||||
$content .= "<ul>";
|
|
||||||
foreach ($successIDs as $id => $label) {
|
|
||||||
$content .= sprintf('<li>%s</li>', $label);
|
|
||||||
}
|
|
||||||
$content .= "</ul>";
|
|
||||||
} else {
|
|
||||||
$content = _t(__CLASS__ . '.NONEREMOVED', 'None removed');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->customise([
|
|
||||||
'Content' => $content,
|
|
||||||
'Form' => ' '
|
|
||||||
])->renderWith('BlankPage');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function removeOrphans($orphanIDs)
|
|
||||||
{
|
|
||||||
$removedOrphans = [];
|
|
||||||
$orphanBaseTable = DataObject::getSchema()->baseDataTable($this->orphanedSearchClass);
|
|
||||||
foreach ($orphanIDs as $id) {
|
|
||||||
/** @var SiteTree $stageRecord */
|
|
||||||
$stageRecord = Versioned::get_one_by_stage(
|
|
||||||
$this->orphanedSearchClass,
|
|
||||||
Versioned::DRAFT,
|
|
||||||
["\"$orphanBaseTable\".\"ID\"" => $id]
|
|
||||||
);
|
|
||||||
if ($stageRecord) {
|
|
||||||
$removedOrphans[$stageRecord->ID] = sprintf('Removed %s (#%d) from Stage', $stageRecord->Title, $stageRecord->ID);
|
|
||||||
$stageRecord->delete();
|
|
||||||
$stageRecord->destroy();
|
|
||||||
unset($stageRecord);
|
|
||||||
}
|
|
||||||
/** @var SiteTree $liveRecord */
|
|
||||||
$liveRecord = Versioned::get_one_by_stage(
|
|
||||||
$this->orphanedSearchClass,
|
|
||||||
Versioned::LIVE,
|
|
||||||
["\"$orphanBaseTable\".\"ID\"" => $id]
|
|
||||||
);
|
|
||||||
if ($liveRecord) {
|
|
||||||
$removedOrphans[$liveRecord->ID] = sprintf('Removed %s (#%d) from Live', $liveRecord->Title, $liveRecord->ID);
|
|
||||||
$liveRecord->doUnpublish();
|
|
||||||
$liveRecord->destroy();
|
|
||||||
unset($liveRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $removedOrphans;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function rebaseHolderTitle()
|
|
||||||
{
|
|
||||||
return sprintf('Rebased Orphans (%s)', date('d/m/Y g:ia', time()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function rebaseOrphans($orphanIDs)
|
|
||||||
{
|
|
||||||
$holder = new SiteTree();
|
|
||||||
$holder->ShowInMenus = 0;
|
|
||||||
$holder->ShowInSearch = 0;
|
|
||||||
$holder->ParentID = 0;
|
|
||||||
$holder->Title = $this->rebaseHolderTitle();
|
|
||||||
$holder->write();
|
|
||||||
|
|
||||||
$removedOrphans = [];
|
|
||||||
$orphanBaseTable = DataObject::getSchema()->baseDataTable($this->orphanedSearchClass);
|
|
||||||
foreach ($orphanIDs as $id) {
|
|
||||||
/** @var SiteTree $stageRecord */
|
|
||||||
$stageRecord = Versioned::get_one_by_stage(
|
|
||||||
$this->orphanedSearchClass,
|
|
||||||
'Stage',
|
|
||||||
["\"$orphanBaseTable\".\"ID\"" => $id]
|
|
||||||
);
|
|
||||||
if ($stageRecord) {
|
|
||||||
$removedOrphans[$stageRecord->ID] = sprintf('Rebased %s (#%d)', $stageRecord->Title, $stageRecord->ID);
|
|
||||||
$stageRecord->ParentID = $holder->ID;
|
|
||||||
$stageRecord->ShowInMenus = 0;
|
|
||||||
$stageRecord->ShowInSearch = 0;
|
|
||||||
$stageRecord->write();
|
|
||||||
$stageRecord->doUnpublish();
|
|
||||||
$stageRecord->destroy();
|
|
||||||
//unset($stageRecord);
|
|
||||||
}
|
|
||||||
/** @var SiteTree $liveRecord */
|
|
||||||
$liveRecord = Versioned::get_one_by_stage(
|
|
||||||
$this->orphanedSearchClass,
|
|
||||||
'Live',
|
|
||||||
["\"$orphanBaseTable\".\"ID\"" => $id]
|
|
||||||
);
|
|
||||||
if ($liveRecord) {
|
|
||||||
$removedOrphans[$liveRecord->ID] = sprintf('Rebased %s (#%d)', $liveRecord->Title, $liveRecord->ID);
|
|
||||||
$liveRecord->ParentID = $holder->ID;
|
|
||||||
$liveRecord->ShowInMenus = 0;
|
|
||||||
$liveRecord->ShowInSearch = 0;
|
|
||||||
$liveRecord->write();
|
|
||||||
if (!$stageRecord) {
|
|
||||||
$liveRecord->doRestoreToStage();
|
|
||||||
}
|
|
||||||
$liveRecord->doUnpublish();
|
|
||||||
$liveRecord->destroy();
|
|
||||||
unset($liveRecord);
|
|
||||||
}
|
|
||||||
if ($stageRecord) {
|
|
||||||
unset($stageRecord);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $removedOrphans;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all orphans from "Stage" and "Live" stages.
|
|
||||||
*
|
|
||||||
* @param string $class
|
|
||||||
* @param array $filter
|
|
||||||
* @param string $sort
|
|
||||||
* @param string $join
|
|
||||||
* @param int|array $limit
|
|
||||||
* @return SS_List
|
|
||||||
*/
|
|
||||||
public function getOrphanedPages($class = SiteTree::class, $filter = [], $sort = null, $join = null, $limit = null)
|
|
||||||
{
|
|
||||||
// Alter condition
|
|
||||||
$table = DataObject::getSchema()->tableName($class);
|
|
||||||
if (empty($filter)) {
|
|
||||||
$where = [];
|
|
||||||
} elseif (is_array($filter)) {
|
|
||||||
$where = $filter;
|
|
||||||
} else {
|
|
||||||
$where = [$filter];
|
|
||||||
}
|
|
||||||
$where[] = ["\"{$table}\".\"ParentID\" != ?" => 0];
|
|
||||||
$where[] = '"Parents"."ID" IS NULL';
|
|
||||||
|
|
||||||
$orphans = new ArrayList();
|
|
||||||
foreach ([Versioned::DRAFT, Versioned::LIVE] as $stage) {
|
|
||||||
$table .= ($stage == Versioned::LIVE) ? '_Live' : '';
|
|
||||||
$stageOrphans = Versioned::get_by_stage(
|
|
||||||
$class,
|
|
||||||
$stage,
|
|
||||||
$where,
|
|
||||||
$sort,
|
|
||||||
null,
|
|
||||||
$limit
|
|
||||||
)->leftJoin($table, "\"$table\".\"ParentID\" = \"Parents\".\"ID\"", "Parents");
|
|
||||||
$orphans->merge($stageOrphans);
|
|
||||||
}
|
|
||||||
|
|
||||||
$orphans->removeDuplicates();
|
|
||||||
|
|
||||||
return $orphans;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tasks;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\ORM\DB;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 4.13.0 Will be removed without equivalent functionality to replace it
|
|
||||||
*/
|
|
||||||
class SiteTreeMaintenanceTask extends Controller
|
|
||||||
{
|
|
||||||
private static $allowed_actions = [
|
|
||||||
'*' => 'ADMIN'
|
|
||||||
];
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
Deprecation::notice(
|
|
||||||
'4.13.0',
|
|
||||||
'Will be removed without equivalent functionality to replace it',
|
|
||||||
Deprecation::SCOPE_CLASS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function makelinksunique()
|
|
||||||
{
|
|
||||||
$table = DataObject::singleton(SiteTree::class)->baseTable();
|
|
||||||
$badURLs = "'" . implode("', '", DB::query("SELECT \"URLSegment\", count(*) FROM \"$table\" GROUP BY \"URLSegment\" HAVING count(*) > 1")->column()) . "'";
|
|
||||||
$pages = DataObject::get(SiteTree::class, "\"$table\".\"URLSegment\" IN ($badURLs)");
|
|
||||||
|
|
||||||
foreach ($pages as $page) {
|
|
||||||
echo "<li>$page->Title: ";
|
|
||||||
$urlSegment = $page->URLSegment;
|
|
||||||
$page->write();
|
|
||||||
if ($urlSegment != $page->URLSegment) {
|
|
||||||
echo _t(
|
|
||||||
'SilverStripe\\CMS\\Model\\SiteTree.LINKSCHANGEDTO',
|
|
||||||
" changed {url1} -> {url2}",
|
|
||||||
['url1' => $urlSegment, 'url2' => $page->URLSegment]
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
echo _t(
|
|
||||||
'SilverStripe\\CMS\\Model\\SiteTree.LINKSALREADYUNIQUE',
|
|
||||||
" {url} is already unique",
|
|
||||||
['url' => $urlSegment]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Link($action = null)
|
|
||||||
{
|
|
||||||
/** @skipUpgrade */
|
|
||||||
return Controller::join_links('SiteTreeMaintenanceTask', $action, '/');
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,19 +19,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"silverstripe/admin": "^1.12@dev",
|
"php": "^8.1",
|
||||||
"silverstripe/campaign-admin": "^1.7@dev",
|
"silverstripe/admin": "^2",
|
||||||
"silverstripe/framework": "^4.11",
|
"silverstripe/campaign-admin": "^2",
|
||||||
"silverstripe/reports": "^4.7@dev",
|
"silverstripe/framework": "^5",
|
||||||
"silverstripe/siteconfig": "^4.7@dev",
|
"silverstripe/reports": "^5",
|
||||||
"silverstripe/versioned": "^1.7@dev",
|
"silverstripe/siteconfig": "^5",
|
||||||
"silverstripe/versioned-admin": "^1.7@dev",
|
"silverstripe/versioned": "^2",
|
||||||
"silverstripe/vendor-plugin": "^1.0",
|
"silverstripe/versioned-admin": "^2",
|
||||||
"php": "^7.4 || ^8.0"
|
"silverstripe/vendor-plugin": "^2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^9.5",
|
||||||
"squizlabs/php_codesniffer": "^3"
|
"squizlabs/php_codesniffer": "^3.7"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"expose": [
|
"expose": [
|
||||||
@ -45,7 +45,10 @@
|
|||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"SilverStripe\\CMS\\": ["code/", "_legacy/"],
|
"SilverStripe\\CMS\\": [
|
||||||
|
"code/",
|
||||||
|
"_legacy/"
|
||||||
|
],
|
||||||
"SilverStripe\\CMS\\Tests\\": "code/php/",
|
"SilverStripe\\CMS\\Tests\\": "code/php/",
|
||||||
"SilverStripe\\CMS\\Tests\\Behaviour\\": "tests/behat/src/"
|
"SilverStripe\\CMS\\Tests\\Behaviour\\": "tests/behat/src/"
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,6 @@ en:
|
|||||||
SilverStripe\CMS\Controllers\CMSSiteTreeFilter_StatusRemovedFromDraftPages:
|
SilverStripe\CMS\Controllers\CMSSiteTreeFilter_StatusRemovedFromDraftPages:
|
||||||
Title: 'Live but removed from draft'
|
Title: 'Live but removed from draft'
|
||||||
SilverStripe\CMS\Controllers\ContentController:
|
SilverStripe\CMS\Controllers\ContentController:
|
||||||
ARCHIVEDSITE: 'Preview version'
|
|
||||||
ARCHIVEDSITEFROM: 'Archived site from'
|
|
||||||
CMS: CMS
|
CMS: CMS
|
||||||
DRAFT: Draft
|
DRAFT: Draft
|
||||||
DRAFTSITE: 'Draft Site'
|
DRAFTSITE: 'Draft Site'
|
||||||
@ -134,11 +132,8 @@ en:
|
|||||||
Password: Password
|
Password: Password
|
||||||
PostInstallTutorialIntro: 'This website is a simplistic version of a SilverStripe 3 site. To extend this, please take a look at {link}.'
|
PostInstallTutorialIntro: 'This website is a simplistic version of a SilverStripe 3 site. To extend this, please take a look at {link}.'
|
||||||
StartEditing: 'You can start editing your content by opening <a href="{link}">the CMS</a>.'
|
StartEditing: 'You can start editing your content by opening <a href="{link}">the CMS</a>.'
|
||||||
UNVERSIONEDPREVIEW: Preview
|
|
||||||
UnableDeleteInstall: 'Unable to delete installation files. Please delete the files below manually'
|
UnableDeleteInstall: 'Unable to delete installation files. Please delete the files below manually'
|
||||||
VIEWPAGEIN: 'View Page in:'
|
VIEWPAGEIN: 'View Page in:'
|
||||||
SilverStripe\CMS\Controllers\SilverStripeNavigator:
|
|
||||||
ARCHIVED: Archived
|
|
||||||
SilverStripe\CMS\Forms\AnchorLinkFormFactory:
|
SilverStripe\CMS\Forms\AnchorLinkFormFactory:
|
||||||
ANCHORVALUE: Anchor
|
ANCHORVALUE: Anchor
|
||||||
SilverStripe\CMS\Forms\InternalLinkFormFactory:
|
SilverStripe\CMS\Forms\InternalLinkFormFactory:
|
||||||
|
78
package.json
78
package.json
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "silverstripe-cms",
|
"name": "silverstripe-cms",
|
||||||
"version": "4.0.0",
|
"version": "5.0.0",
|
||||||
"description": "The SilverStripe CMS",
|
"description": "The SilverStripe CMS",
|
||||||
"directories": {
|
"directories": {
|
||||||
"test": "tests"
|
"test": "tests"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^10.x"
|
"node": "^18.x"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn && yarn test && NODE_ENV=production webpack -p --bail --progress",
|
"build": "yarn && yarn lint && yarn test && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress",
|
||||||
"dev": "NODE_ENV=development webpack --progress",
|
"dev": "NODE_ENV=development webpack --progress",
|
||||||
"watch": "NODE_ENV=development webpack --watch --progress",
|
"watch": "NODE_ENV=development webpack --watch --progress",
|
||||||
"css": "WEBPACK_CHILD=css npm run build",
|
"css": "WEBPACK_CHILD=css npm run build",
|
||||||
@ -32,39 +32,51 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/silverstripe/silverstripe-cms#readme",
|
"homepage": "https://github.com/silverstripe/silverstripe-cms#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@silverstripe/reactstrap-confirm": "0.0.5",
|
"@apollo/client": "^3.7.1",
|
||||||
"apollo-client": "^2.4.2",
|
"@popperjs/core": "^2.11.6",
|
||||||
"bootstrap": "^4.3.1",
|
"bootstrap": "^4.6.2",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.3.2",
|
||||||
"deep-freeze-strict": "^1.1.1",
|
"deep-freeze-strict": "^1.1.1",
|
||||||
"graphql": "^14.0.0",
|
"graphql": "^16.6.0",
|
||||||
"graphql-tag": "^2.10.0",
|
"graphql-tag": "^2.12.6",
|
||||||
"isomorphic-fetch": "^2.2.1",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"jquery": "^3.5.0",
|
|
||||||
"merge": "^2.1.1",
|
"merge": "^2.1.1",
|
||||||
"popper.js": "^1.14.4",
|
"prop-types": "^15.8.1",
|
||||||
"prop-types": "^15.6.2",
|
"react": "^18.2.0",
|
||||||
"react": "^16.6.1",
|
"react-dom": "^18.2.0",
|
||||||
"react-apollo": "^2.1.11",
|
"react-redux": "^8.0.5",
|
||||||
"react-dom": "^16.6.1",
|
"react-select": "^5.6.0",
|
||||||
"react-redux": "^5.0.7",
|
"reactstrap": "^8.9.0",
|
||||||
"react-select": "^1.3",
|
"reactstrap-confirm": "^1.3.2",
|
||||||
"reactstrap": "^6.4.0",
|
"redux": "^4.2.0",
|
||||||
"redux": "^4.0.0",
|
"redux-form": "^8.3.8"
|
||||||
"redux-form": "^7.4.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@silverstripe/eslint-config": "^0.1.0",
|
"@silverstripe/eslint-config": "^1.0.0",
|
||||||
"@silverstripe/webpack-config": "^1.3.0",
|
"@silverstripe/webpack-config": "^2.0.0",
|
||||||
"babel-jest": "^23.6.0",
|
"babel-jest": "^29.3.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"copy-webpack-plugin": "^4",
|
"core-js": "^3.26.0",
|
||||||
"jest-cli": "^23.6.0"
|
"jest-cli": "^29.3.0",
|
||||||
|
"jest-environment-jsdom": "^29.3.1",
|
||||||
|
"react-16": "npm:react@^16.14.0",
|
||||||
|
"react-dom-16": "npm:react-dom@^16.14.0",
|
||||||
|
"webpack": "^5.74.0",
|
||||||
|
"webpack-cli": "^5.0.0"
|
||||||
},
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"defaults"
|
||||||
|
],
|
||||||
"jest": {
|
"jest": {
|
||||||
|
"testEnvironment": "jsdom",
|
||||||
"roots": [
|
"roots": [
|
||||||
"client/src"
|
"client/src"
|
||||||
],
|
],
|
||||||
|
"moduleNameMapper": {
|
||||||
|
"^react-dom/client$": "react-dom-16",
|
||||||
|
"^react-dom((/.*)?)$": "react-dom-16$1",
|
||||||
|
"^react((/.*)?)$": "react-16$1"
|
||||||
|
},
|
||||||
"moduleDirectories": [
|
"moduleDirectories": [
|
||||||
"client/src",
|
"client/src",
|
||||||
"node_modules",
|
"node_modules",
|
||||||
@ -82,16 +94,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"colors": "1.1.2",
|
"colors": "1.4.0"
|
||||||
"eslint": "^4.6.1"
|
|
||||||
},
|
|
||||||
"babel": {
|
|
||||||
"presets": [
|
|
||||||
"env",
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"transform-object-rest-spread"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
<div class="cms-preview fill-height flexbox-area-grow" data-layout-type="border">
|
|
||||||
<div class="panel flexbox-area-grow fill-height">
|
|
||||||
<div class="preview-note">
|
|
||||||
<div class="icon font-icon-monitor display-1"></div>
|
|
||||||
<%t SilverStripe\CMS\Controllers\CMSPageHistoryController.NO_PREVIEW 'No preview available' %>
|
|
||||||
</div>
|
|
||||||
<div class="preview__device">
|
|
||||||
<div class="preview-device-outer">
|
|
||||||
<div class="preview-device-inner">
|
|
||||||
<iframe src="about:blank" class="center" name="cms-preview-iframe"></iframe>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="toolbar toolbar--south cms-content-controls cms-preview-controls"></div>
|
|
||||||
</div>
|
|
@ -1,27 +0,0 @@
|
|||||||
<% if $BackLinkTracking %>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><%t SilverStripe\CMS\Model\SiteTreeFileExtension.TITLE_INDEX '#' %></th>
|
|
||||||
<th><%t SilverStripe\CMS\Model\SiteTreeFileExtension.TITLE_USED_ON 'Used on' %></th>
|
|
||||||
<th><%t SilverStripe\CMS\Model\SiteTreeFileExtension.TITLE_TYPE 'Type' %></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<% loop $BackLinkTracking %>
|
|
||||||
<tr>
|
|
||||||
<td>$Pos</td>
|
|
||||||
<td><a href="$CMSEditLink">$MenuTitle</a></td>
|
|
||||||
<td>
|
|
||||||
$i18n_singular_name
|
|
||||||
<% if $isPublished %>
|
|
||||||
<span class="badge badge-success">Published</span>
|
|
||||||
<% else %>
|
|
||||||
<span class="badge status-addedtodraft">Draft</span>
|
|
||||||
<% end_if %>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<% end_loop %>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<% end_if %>
|
|
@ -81,19 +81,19 @@ Feature: Edit a page
|
|||||||
When I click on "About Us" in the tree
|
When I click on "About Us" in the tree
|
||||||
|
|
||||||
# Embed files from the "Files" section of the admin area
|
# Embed files from the "Files" section of the admin area
|
||||||
And I click on the "div[aria-label='Insert from Files'] button" element
|
And I press the "Insert from Files" HTML field button
|
||||||
And I click on the ".gallery__files .gallery-item__thumbnail" element
|
And I click on the ".gallery__files .gallery-item__thumbnail" element
|
||||||
And I press the "Insert file" button
|
And I press the "Insert file" button
|
||||||
|
|
||||||
# Link to a file in the "Files" section of the admin area
|
# Link to a file in the "Files" section of the admin area
|
||||||
And I click on the "div[aria-label='Insert link [Ctrl+K]'] button" element
|
And I press the "Insert link" HTML field button
|
||||||
And I select "Link to a file" from the TinyMCE menu with javascript
|
And I click "Link to a file" in the ".tox-collection__group" element
|
||||||
And I click on the ".gallery__files .gallery-item__thumbnail" element
|
And I click on the ".gallery__files .gallery-item__thumbnail" element
|
||||||
And I fill in "Form_fileInsertForm_Text" with "MyImage"
|
And I fill in "Form_fileInsertForm_Text" with "MyImage"
|
||||||
And I press the "Link to file" button
|
And I press the "Link to file" button
|
||||||
|
|
||||||
# Embed media from a URL
|
# Embed media from a URL
|
||||||
And I click on the "div[aria-label='Insert media via URL'] button" element
|
And I press the "Insert media via URL" button
|
||||||
And I fill in "Form_remoteCreateForm_Url" with "https://www.youtube.com/watch?v=ScMzIvxBSi4"
|
And I fill in "Form_remoteCreateForm_Url" with "https://www.youtube.com/watch?v=ScMzIvxBSi4"
|
||||||
And I press "Add media"
|
And I press "Add media"
|
||||||
And I wait for 15 seconds
|
And I wait for 15 seconds
|
||||||
|
@ -16,12 +16,11 @@ So that I can link to a external website or a page on my site
|
|||||||
Scenario: I can link to an internal page
|
Scenario: I can link to an internal page
|
||||||
When I select "awesome" in the "Content" HTML field
|
When I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
And I click "Page on this site" in the ".mce-menu" element
|
And I click "Page on this site" in the ".tox-collection__group" element
|
||||||
Then I should see an "form#Form_editorInternalLink" element
|
Then I should see an "form#Form_editorInternalLink" element
|
||||||
When I click "(Search or choose Page)" in the ".Select-multi-value-wrapper" element
|
When I select "About Us" in the "#Form_editorInternalLink_PageID_Holder" tree dropdown
|
||||||
And I click "About Us" in the ".treedropdownfield__menu" element
|
|
||||||
And I fill in "my desc" for "Link description"
|
And I fill in "my desc" for "Link description"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]">awesome</a>"
|
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
@ -30,15 +29,14 @@ So that I can link to a external website or a page on my site
|
|||||||
Given I fill in the "Content" HTML field with "<a title='my desc' href='[sitetree_link,id=2]'>awesome</a>"
|
Given I fill in the "Content" HTML field with "<a title='my desc' href='[sitetree_link,id=2]'>awesome</a>"
|
||||||
And I select "awesome" in the "Content" HTML field
|
And I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
And I click "Page on this site" in the ".mce-menu" element
|
And I click "Page on this site" in the ".tox-collection__group" element
|
||||||
And I should see an "form#Form_editorInternalLink" element
|
And I should see an "form#Form_editorInternalLink" element
|
||||||
Then I should see "About Us" in the ".Select-value" element
|
Then I should see "About Us" in the "#Form_editorInternalLink_PageID_Holder .treedropdownfield__value-container" element
|
||||||
And the "Link description" field should contain "my desc"
|
And the "Link description" field should contain "my desc"
|
||||||
# This doesn't seem to suffer from that issue
|
# This doesn't seem to suffer from that issue
|
||||||
When I click "About Us" in the ".Select-value" element
|
When I select "Home" in the "#Form_editorInternalLink_PageID_Holder" tree dropdown
|
||||||
And I click "Home" in the ".treedropdownfield__menu" element
|
|
||||||
And I fill in "my new desc" for "Link description"
|
And I fill in "my new desc" for "Link description"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a title="my new desc" href="[sitetree_link,id=1]">awesome</a>"
|
Then the "Content" HTML field should contain "<a title="my new desc" href="[sitetree_link,id=1]">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
@ -46,11 +44,11 @@ So that I can link to a external website or a page on my site
|
|||||||
Scenario: I can link to an external URL
|
Scenario: I can link to an external URL
|
||||||
Given I select "awesome" in the "Content" HTML field
|
Given I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
When I click "Link to external URL" in the ".mce-menu" element
|
When I click "Link to external URL" in the ".tox-collection__group" element
|
||||||
And I should see an "form#Form_ModalsEditorExternalLink" element
|
And I should see an "form#Form_ModalsEditorExternalLink" element
|
||||||
When I fill in "http://silverstripe.org" for "URL"
|
When I fill in "http://silverstripe.org" for "URL"
|
||||||
And I check "Open in new window/tab"
|
And I check "Open in new window/tab"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a rel="noopener" href="http://silverstripe.org" target="_blank">awesome</a>"
|
Then the "Content" HTML field should contain "<a rel="noopener" href="http://silverstripe.org" target="_blank">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
@ -59,12 +57,12 @@ So that I can link to a external website or a page on my site
|
|||||||
Given I fill in the "Content" HTML field with "<p>My <a href='http://silverstripe.org'>awesome</a> content"
|
Given I fill in the "Content" HTML field with "<p>My <a href='http://silverstripe.org'>awesome</a> content"
|
||||||
And I select "awesome" in the "Content" HTML field
|
And I select "awesome" in the "Content" HTML field
|
||||||
When I press the "Insert link" HTML field button
|
When I press the "Insert link" HTML field button
|
||||||
And I click "Link to external URL" in the ".mce-menu" element
|
And I click "Link to external URL" in the ".tox-collection__group" element
|
||||||
And I should see an "form#Form_ModalsEditorExternalLink" element
|
And I should see an "form#Form_ModalsEditorExternalLink" element
|
||||||
Then the "URL" field should contain "http://silverstripe.org"
|
Then the "URL" field should contain "http://silverstripe.org"
|
||||||
# This doesn't seem to suffer from that issue
|
# This doesn't seem to suffer from that issue
|
||||||
When I fill in "http://google.com" for "URL"
|
When I fill in "http://google.com" for "URL"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a href="http://google.com">awesome</a>"
|
Then the "Content" HTML field should contain "<a href="http://google.com">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
|
@ -17,16 +17,14 @@ So that I can link to a external website or a page on my site
|
|||||||
Scenario: I can link to an anchor in an internal page
|
Scenario: I can link to an anchor in an internal page
|
||||||
When I select "awesome" in the "Content" HTML field
|
When I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
And I click "Anchor on a page" in the ".mce-menu" element
|
And I click "Anchor on a page" in the ".tox-collection__group" element
|
||||||
Then I should see an "form#Form_editorAnchorLink" element
|
Then I should see an "form#Form_editorAnchorLink" element
|
||||||
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
|
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .treedropdownfield__value-container" element
|
||||||
When I click "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
|
When I select "Details" in the "#Form_editorAnchorLink_PageID_Holder" tree dropdown
|
||||||
And I click "Details" in the "#Form_editorAnchorLink_PageID_Holder .Select-menu-outer" element
|
And I select "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder" anchor dropdown
|
||||||
And I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
|
Then I should see "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .anchorselectorfield__value-container" element
|
||||||
And I click "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
|
||||||
Then I should see "youranchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
|
|
||||||
When I fill in "my desc" for "Link description"
|
When I fill in "my desc" for "Link description"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=3]#youranchor">awesome</a>"
|
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=3]#youranchor">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
@ -34,15 +32,13 @@ So that I can link to a external website or a page on my site
|
|||||||
Scenario: I can link to an anchor from a dataobject on the current page
|
Scenario: I can link to an anchor from a dataobject on the current page
|
||||||
When I select "awesome" in the "Content" HTML field
|
When I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
And I click "Anchor on a page" in the ".mce-menu" element
|
And I click "Anchor on a page" in the ".tox-collection__group" element
|
||||||
Then I should see an "form#Form_editorAnchorLink" element
|
Then I should see an "form#Form_editorAnchorLink" element
|
||||||
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
|
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .treedropdownfield__value-container" element
|
||||||
When I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
|
When I select "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder" anchor dropdown
|
||||||
Then I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
Then I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .anchorselectorfield__value-container" element
|
||||||
When I click "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
|
||||||
Then I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
|
|
||||||
When I fill in "my desc" for "Link description"
|
When I fill in "my desc" for "Link description"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#dataobject-anchor">awesome</a>"
|
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#dataobject-anchor">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
@ -51,16 +47,15 @@ So that I can link to a external website or a page on my site
|
|||||||
Given I fill in the "Content" HTML field with "<p>My awesome content</p><p><a id='unsaved-anchor'></a>unsaved content</p>"
|
Given I fill in the "Content" HTML field with "<p>My awesome content</p><p><a id='unsaved-anchor'></a>unsaved content</p>"
|
||||||
When I select "awesome" in the "Content" HTML field
|
When I select "awesome" in the "Content" HTML field
|
||||||
And I press the "Insert link" HTML field button
|
And I press the "Insert link" HTML field button
|
||||||
And I click "Anchor on a page" in the ".mce-menu" element
|
And I click "Anchor on a page" in the ".tox-collection__group" element
|
||||||
Then I should see an "form#Form_editorAnchorLink" element
|
Then I should see an "form#Form_editorAnchorLink" element
|
||||||
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .Select-multi-value-wrapper" element
|
And I should see "About Us" in the "#Form_editorAnchorLink_PageID_Holder .treedropdownfield__value-container" element
|
||||||
When I click "Select or enter anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-multi-value-wrapper" element
|
When I click on the ".anchorselectorfield__dropdown-indicator" element
|
||||||
Then I should see "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
Then I should see "dataobject-anchor" in the ".anchorselectorfield__menu-list" element
|
||||||
And I should see "dataobject-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
When I select "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder" anchor dropdown
|
||||||
When I click "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-menu-outer" element
|
Then I should see "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .anchorselectorfield__value-container" element
|
||||||
Then I should see "unsaved-anchor" in the "#Form_editorAnchorLink_Anchor_Holder .Select-value" element
|
|
||||||
When I fill in "my desc" for "Link description"
|
When I fill in "my desc" for "Link description"
|
||||||
And I press the "Insert" button
|
And I press the "Insert link" button
|
||||||
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#unsaved-anchor">awesome</a>"
|
Then the "Content" HTML field should contain "<a title="my desc" href="[sitetree_link,id=2]#unsaved-anchor">awesome</a>"
|
||||||
# Required to avoid "unsaved changes" browser dialog
|
# Required to avoid "unsaved changes" browser dialog
|
||||||
Then I press the "Save" button
|
Then I press the "Save" button
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
@gsat
|
|
||||||
Feature: Redirector Pages
|
Feature: Redirector Pages
|
||||||
As an author
|
As an author
|
||||||
I want to redirect to a different location
|
I want to redirect to a different location
|
||||||
|
@ -8,6 +8,7 @@ use Behat\Mink\Element\NodeElement;
|
|||||||
use PHPUnit\Framework\Assert;
|
use PHPUnit\Framework\Assert;
|
||||||
use SilverStripe\BehatExtension\Context\BasicContext;
|
use SilverStripe\BehatExtension\Context\BasicContext;
|
||||||
use SilverStripe\BehatExtension\Context\FixtureContext as BehatFixtureContext;
|
use SilverStripe\BehatExtension\Context\FixtureContext as BehatFixtureContext;
|
||||||
|
use SilverStripe\BehatExtension\Utility\StepHelper;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Core\ClassInfo;
|
use SilverStripe\Core\ClassInfo;
|
||||||
@ -20,6 +21,8 @@ use SilverStripe\Versioned\Versioned;
|
|||||||
*/
|
*/
|
||||||
class FixtureContext extends BehatFixtureContext
|
class FixtureContext extends BehatFixtureContext
|
||||||
{
|
{
|
||||||
|
use StepHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var BasicContext
|
* @var BasicContext
|
||||||
*/
|
*/
|
||||||
@ -118,22 +121,6 @@ class FixtureContext extends BehatFixtureContext
|
|||||||
Assert::assertEquals($value, $radioButton->getAttribute($attribute));
|
Assert::assertEquals($value, $radioButton->getAttribute($attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Assumes you've just opened the Insert link menu, e.g.
|
|
||||||
* I click on the "div[aria-label='Insert link [Ctrl+K]'] button" element
|
|
||||||
*
|
|
||||||
* @When /^I select "(.+?)" from the TinyMCE menu with javascript$/
|
|
||||||
* @param string $label
|
|
||||||
*/
|
|
||||||
public function iSelectFromTheTinyMceMenu($label)
|
|
||||||
{
|
|
||||||
// :visible and :contains are jQuery css selectors
|
|
||||||
$js = <<<JS
|
|
||||||
jQuery(".mce-menu-item:visible span:contains('{$label}')").click();
|
|
||||||
JS;
|
|
||||||
$this->getMainContext()->getSession()->executeScript($js);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* e.g. --PageOne,--PageTwo,---PageTwoChild,--PageThree
|
* e.g. --PageOne,--PageTwo,---PageTwoChild,--PageThree
|
||||||
*
|
*
|
||||||
@ -155,4 +142,33 @@ JS;
|
|||||||
$actual = $this->getMainContext()->getSession()->evaluateScript($js);
|
$actual = $this->getMainContext()->getSession()->evaluateScript($js);
|
||||||
Assert::assertEquals($expected, $actual);
|
Assert::assertEquals($expected, $actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a value in the anchor selector field
|
||||||
|
*
|
||||||
|
* @When /^I select "([^"]*)" in the "([^"]*)" anchor dropdown$/
|
||||||
|
*/
|
||||||
|
public function iSelectValueInAnchorDropdown($text, $selector)
|
||||||
|
{
|
||||||
|
$page = $this->getMainContext()->getSession()->getPage();
|
||||||
|
/** @var NodeElement $parentElement */
|
||||||
|
$parentElement = null;
|
||||||
|
$this->retryThrowable(function () use (&$parentElement, &$page, $selector) {
|
||||||
|
$parentElement = $page->find('css', $selector);
|
||||||
|
Assert::assertNotNull($parentElement, sprintf('"%s" element not found', $selector));
|
||||||
|
$page = $this->getMainContext()->getSession()->getPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->retryThrowable(function () use ($parentElement, $selector) {
|
||||||
|
$dropdown = $parentElement->find('css', '.anchorselectorfield__dropdown-indicator');
|
||||||
|
Assert::assertNotNull($dropdown, sprintf('Unable to find the dropdown in "%s"', $selector));
|
||||||
|
$dropdown->click();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->retryThrowable(function () use ($text, $parentElement, $selector) {
|
||||||
|
$element = $parentElement->find('xpath', sprintf('//*[count(*)=0 and .="%s"]', $text));
|
||||||
|
Assert::assertNotNull($element, sprintf('"%s" not found in "%s"', $text, $selector));
|
||||||
|
$element->click();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ use SilverStripe\Versioned\Versioned;
|
|||||||
*/
|
*/
|
||||||
class CMSBatchActionsTest extends SapphireTest
|
class CMSBatchActionsTest extends SapphireTest
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $fixture_file = 'CMSBatchActionsTest.yml';
|
protected static $fixture_file = 'CMSBatchActionsTest.yml';
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
@ -142,10 +141,10 @@ class CMSBatchActionsTest extends SapphireTest
|
|||||||
$this->assertEquals($archivedID, $list->first()->ParentID);
|
$this->assertEquals($archivedID, $list->first()->ParentID);
|
||||||
|
|
||||||
// Run restore
|
// Run restore
|
||||||
$result = json_decode($action->run($list) ?? '', true);
|
$result = json_decode($action->run($list)->getBody(), true);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
[
|
[
|
||||||
$archivedxID => $archivedxID
|
$archivedxID => $archivedxID,
|
||||||
],
|
],
|
||||||
$result['success']
|
$result['success']
|
||||||
);
|
);
|
||||||
@ -162,13 +161,13 @@ class CMSBatchActionsTest extends SapphireTest
|
|||||||
$this->assertEquals(0, $list->last()->ParentID); // archived (parent)
|
$this->assertEquals(0, $list->last()->ParentID); // archived (parent)
|
||||||
|
|
||||||
// Run restore
|
// Run restore
|
||||||
$result = json_decode($action->run($list) ?? '', true);
|
$result = json_decode($action->run($list)->getBody(), true);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
[
|
[
|
||||||
// Order of archived is opposite to order items are passed in, as
|
// Order of archived is opposite to order items are passed in, as
|
||||||
// these are sorted by level first
|
// these are sorted by level first
|
||||||
$archivedID => $archivedID,
|
$archivedID => $archivedID,
|
||||||
$archivedyID => $archivedyID
|
$archivedyID => $archivedyID,
|
||||||
],
|
],
|
||||||
$result['success']
|
$result['success']
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use SilverStripe\Admin\CMSBatchActionHandler;
|
use SilverStripe\Admin\CMSBatchActionHandler;
|
||||||
use SilverStripe\CMS\Controllers\CMSMain;
|
use SilverStripe\CMS\Controllers\CMSMain;
|
||||||
@ -25,7 +24,6 @@ use SilverStripe\Security\Member;
|
|||||||
use SilverStripe\Security\Security;
|
use SilverStripe\Security\Security;
|
||||||
use SilverStripe\SiteConfig\SiteConfig;
|
use SilverStripe\SiteConfig\SiteConfig;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
|
|
||||||
class CMSMainTest extends FunctionalTest
|
class CMSMainTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
@ -119,40 +117,6 @@ class CMSMainTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Test the results of a publication better
|
|
||||||
*/
|
|
||||||
public function testPublish()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$page1 = $this->objFromFixture(Page::class, "page1");
|
|
||||||
$page2 = $this->objFromFixture(Page::class, "page2");
|
|
||||||
$this->logInAs('admin');
|
|
||||||
|
|
||||||
$response = $this->get('admin/pages/publishall?confirm=1');
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
'Done: Published 30 pages',
|
|
||||||
$response->getBody()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Some modules (e.g., cmsworkflow) will remove this action
|
|
||||||
$actions = CMSBatchActionHandler::config()->batch_actions;
|
|
||||||
if (isset($actions['publish'])) {
|
|
||||||
$response = $this->get('admin/pages/batchactions/publish?ajax=1&csvIDs=' . implode(',', [$page1->ID, $page2->ID]));
|
|
||||||
$responseData = json_decode($response->getBody() ?? '', true);
|
|
||||||
$this->assertArrayHasKey($page1->ID, $responseData['modified']);
|
|
||||||
$this->assertArrayHasKey($page2->ID, $responseData['modified']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the latest version of the redirector page
|
|
||||||
$pageID = $this->idFromFixture(RedirectorPage::class, 'page5');
|
|
||||||
$latestID = DB::prepared_query('select max("Version") from "RedirectorPage_Versions" where "RecordID" = ?', [$pageID])->value();
|
|
||||||
$dsCount = DB::prepared_query('select count("Version") from "RedirectorPage_Versions" where "RecordID" = ? and "Version"= ?', [$pageID, $latestID])->value();
|
|
||||||
$this->assertEquals(1, $dsCount, "Published page has no duplicate version records: it has " . $dsCount . " for version " . $latestID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that getCMSFields works on each page type.
|
* Test that getCMSFields works on each page type.
|
||||||
* Mostly, this is just checking that the method doesn't return an error
|
* Mostly, this is just checking that the method doesn't return an error
|
||||||
@ -185,8 +149,8 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
||||||
$parentPage = $this->objFromFixture(Page::class, 'page3');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$childPage = $this->objFromFixture(Page::class, 'page1');
|
$childPage = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
$parentPage->doUnpublish();
|
$parentPage->doUnpublish();
|
||||||
$childPage->doUnpublish();
|
$childPage->doUnpublish();
|
||||||
@ -208,7 +172,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
// Set up a page that is delete from live
|
// Set up a page that is delete from live
|
||||||
$page = $this->objFromFixture(Page::class, 'page1');
|
$page = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$page->publishRecursive();
|
$page->publishRecursive();
|
||||||
$page->delete();
|
$page->delete();
|
||||||
@ -216,7 +180,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$response = $this->get('admin/pages/edit/show/' . $pageID);
|
$response = $this->get('admin/pages/edit/show/' . $pageID);
|
||||||
|
|
||||||
$livePage = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, [
|
$livePage = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, [
|
||||||
'"SiteTree"."ID"' => $pageID
|
'"SiteTree"."ID"' => $pageID,
|
||||||
]);
|
]);
|
||||||
$this->assertInstanceOf(SiteTree::class, $livePage);
|
$this->assertInstanceOf(SiteTree::class, $livePage);
|
||||||
$this->assertTrue($livePage->canDelete());
|
$this->assertTrue($livePage->canDelete());
|
||||||
@ -233,7 +197,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
// Set up a page that is delete from live
|
// Set up a page that is delete from live
|
||||||
$page1 = $this->objFromFixture(Page::class, 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page1ID = $page1->ID;
|
$page1ID = $page1->ID;
|
||||||
$page1->publishRecursive();
|
$page1->publishRecursive();
|
||||||
$page1->delete();
|
$page1->delete();
|
||||||
@ -246,18 +210,18 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->assertNull($cmsMain->getRecord('asdf'));
|
$this->assertNull($cmsMain->getRecord('asdf'));
|
||||||
|
|
||||||
// Pages that are on draft and aren't on draft should both work
|
// Pages that are on draft and aren't on draft should both work
|
||||||
$this->assertInstanceOf('Page', $cmsMain->getRecord($page1ID));
|
$this->assertInstanceOf(SiteTree::class, $cmsMain->getRecord($page1ID));
|
||||||
$this->assertInstanceOf('Page', $cmsMain->getRecord($this->idFromFixture('Page', 'page2')));
|
$this->assertInstanceOf(SiteTree::class, $cmsMain->getRecord($this->idFromFixture(SiteTree::class, 'page2')));
|
||||||
|
|
||||||
// This functionality isn't actually used any more.
|
// This functionality isn't actually used any more.
|
||||||
$newPage = $cmsMain->getRecord('new-Page-5');
|
$newPage = $cmsMain->getRecord('new-Page-5');
|
||||||
$this->assertInstanceOf('Page', $newPage);
|
$this->assertInstanceOf(SiteTree::class, $newPage);
|
||||||
$this->assertEquals('5', $newPage->ParentID);
|
$this->assertEquals('5', $newPage->ParentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeletedPagesSiteTreeFilter()
|
public function testDeletedPagesSiteTreeFilter()
|
||||||
{
|
{
|
||||||
$id = $this->idFromFixture('Page', 'page3');
|
$id = $this->idFromFixture(SiteTree::class, 'page3');
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$result = $this->get('admin/pages/getsubtree?filter=CMSSiteTreeFilter_DeletedPages&ajax=1&ID=' . $id);
|
$result = $this->get('admin/pages/getsubtree?filter=CMSSiteTreeFilter_DeletedPages&ajax=1&ID=' . $id);
|
||||||
$this->assertEquals(200, $result->getStatusCode());
|
$this->assertEquals(200, $result->getStatusCode());
|
||||||
@ -278,7 +242,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
'admin/pages/add/AddForm',
|
'admin/pages/add/AddForm',
|
||||||
[
|
[
|
||||||
'ParentID' => '0',
|
'ParentID' => '0',
|
||||||
'PageType' => 'Page',
|
'PageType' => RedirectorPage::class,
|
||||||
'Locale' => 'en_US',
|
'Locale' => 'en_US',
|
||||||
'action_doAdd' => 1,
|
'action_doAdd' => 1,
|
||||||
'ajax' => 1,
|
'ajax' => 1,
|
||||||
@ -298,7 +262,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
'admin/pages/add/AddForm',
|
'admin/pages/add/AddForm',
|
||||||
[
|
[
|
||||||
'ParentID' => '0',
|
'ParentID' => '0',
|
||||||
'PageType' => 'Page',
|
'PageType' => RedirectorPage::class,
|
||||||
'Locale' => 'en_US',
|
'Locale' => 'en_US',
|
||||||
'action_doAdd' => 1,
|
'action_doAdd' => 1,
|
||||||
'ajax' => 1,
|
'ajax' => 1,
|
||||||
@ -332,7 +296,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
'PageType' => CMSMainTest_ClassA::class,
|
'PageType' => CMSMainTest_ClassA::class,
|
||||||
'Locale' => 'en_US',
|
'Locale' => 'en_US',
|
||||||
'action_doAdd' => 1,
|
'action_doAdd' => 1,
|
||||||
'ajax' => 1
|
'ajax' => 1,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
||||||
@ -352,7 +316,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
'PageType' => CMSMainTest_ClassB::class,
|
'PageType' => CMSMainTest_ClassB::class,
|
||||||
'Locale' => 'en_US',
|
'Locale' => 'en_US',
|
||||||
'action_doAdd' => 1,
|
'action_doAdd' => 1,
|
||||||
'ajax' => 1
|
'ajax' => 1,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
||||||
@ -375,10 +339,10 @@ class CMSMainTest extends FunctionalTest
|
|||||||
'admin/pages/add/AddForm',
|
'admin/pages/add/AddForm',
|
||||||
[
|
[
|
||||||
'ParentID' => $newPageId,
|
'ParentID' => $newPageId,
|
||||||
'PageType' => 'Page',
|
'PageType' => RedirectorPage::class,
|
||||||
'Locale' => 'en_US',
|
'Locale' => 'en_US',
|
||||||
'action_doAdd' => 1,
|
'action_doAdd' => 1,
|
||||||
'ajax' => 1
|
'ajax' => 1,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
'X-Pjax' => 'CurrentForm,Breadcrumbs',
|
||||||
@ -393,8 +357,8 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testBreadcrumbs()
|
public function testBreadcrumbs()
|
||||||
{
|
{
|
||||||
$page3 = $this->objFromFixture(Page::class, 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$page31 = $this->objFromFixture(Page::class, 'page31');
|
$page31 = $this->objFromFixture(SiteTree::class, 'page31');
|
||||||
$this->logInAs('admin');
|
$this->logInAs('admin');
|
||||||
|
|
||||||
$response = $this->get('admin/pages/edit/show/' . $page31->ID);
|
$response = $this->get('admin/pages/edit/show/' . $page31->ID);
|
||||||
@ -420,7 +384,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
$this->assertEquals($page->Title, 'New Page');
|
$this->assertEquals($page->Title, 'New Page');
|
||||||
$this->assertNotEquals($page->Sort, 0);
|
$this->assertNotEquals($page->Sort, 0);
|
||||||
$this->assertInstanceOf('Page', $page);
|
$this->assertInstanceOf(SiteTree::class, $page);
|
||||||
|
|
||||||
// Test failure
|
// Test failure
|
||||||
try {
|
try {
|
||||||
@ -449,10 +413,10 @@ class CMSMainTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Change state of tree
|
// Change state of tree
|
||||||
$page1 = $this->objFromFixture(Page::class, 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page3 = $this->objFromFixture(Page::class, 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$page11 = $this->objFromFixture(Page::class, 'page11');
|
$page11 = $this->objFromFixture(SiteTree::class, 'page11');
|
||||||
$page12 = $this->objFromFixture(Page::class, 'page12');
|
$page12 = $this->objFromFixture(SiteTree::class, 'page12');
|
||||||
// Deleted
|
// Deleted
|
||||||
$page1->doUnpublish();
|
$page1->doUnpublish();
|
||||||
$page1->delete();
|
$page1->delete();
|
||||||
@ -472,7 +436,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
// Test deleted page filter
|
// Test deleted page filter
|
||||||
$params = [
|
$params = [
|
||||||
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_StatusDeletedPages'
|
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_StatusDeletedPages',
|
||||||
];
|
];
|
||||||
$pages = $controller->getList($params);
|
$pages = $controller->getList($params);
|
||||||
$this->assertEquals(1, $pages->count());
|
$this->assertEquals(1, $pages->count());
|
||||||
@ -483,7 +447,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
// Test live, but not on draft filter
|
// Test live, but not on draft filter
|
||||||
$params = [
|
$params = [
|
||||||
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_StatusRemovedFromDraftPages'
|
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_StatusRemovedFromDraftPages',
|
||||||
];
|
];
|
||||||
$pages = $controller->getList($params);
|
$pages = $controller->getList($params);
|
||||||
$this->assertEquals(1, $pages->count());
|
$this->assertEquals(1, $pages->count());
|
||||||
@ -494,7 +458,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
|
|
||||||
// Test live pages filter
|
// Test live pages filter
|
||||||
$params = [
|
$params = [
|
||||||
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_PublishedPages'
|
'FilterClass' => 'SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter_PublishedPages',
|
||||||
];
|
];
|
||||||
$pages = $controller->getList($params);
|
$pages = $controller->getList($params);
|
||||||
$this->assertEquals(2, $pages->count());
|
$this->assertEquals(2, $pages->count());
|
||||||
@ -529,7 +493,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$this->loginWithPermission('ADMIN');
|
$this->loginWithPermission('ADMIN');
|
||||||
|
|
||||||
// Get a associated with a fixture page.
|
// Get a associated with a fixture page.
|
||||||
$page = $this->objFromFixture(Page::class, 'page1');
|
$page = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$controller = CMSMain::create();
|
$controller = CMSMain::create();
|
||||||
$controller->setRequest(Controller::curr()->getRequest());
|
$controller->setRequest(Controller::curr()->getRequest());
|
||||||
$form = $controller->getEditForm($page->ID);
|
$form = $controller->getEditForm($page->ID);
|
||||||
@ -557,7 +521,7 @@ class CMSMainTest extends FunctionalTest
|
|||||||
$form->loadDataFrom(['ClassName' => CMSMainTest_ClassB::class]);
|
$form->loadDataFrom(['ClassName' => CMSMainTest_ClassB::class]);
|
||||||
$result = $cms->save([
|
$result = $cms->save([
|
||||||
'ID' => $page->ID,
|
'ID' => $page->ID,
|
||||||
'ClassName' => CMSMainTest_ClassB::class
|
'ClassName' => CMSMainTest_ClassB::class,
|
||||||
], $form);
|
], $form);
|
||||||
$this->assertEquals(200, $result->getStatusCode());
|
$this->assertEquals(200, $result->getStatusCode());
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
page1:
|
page1:
|
||||||
Title: Page 1
|
Title: Page 1
|
||||||
Sort: 1
|
Sort: 1
|
||||||
@ -10,11 +10,11 @@ Page:
|
|||||||
Sort: 3
|
Sort: 3
|
||||||
page31:
|
page31:
|
||||||
Title: Page 3.1
|
Title: Page 3.1
|
||||||
Parent: =>Page.page3
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page3
|
||||||
Sort: 1
|
Sort: 1
|
||||||
page32:
|
page32:
|
||||||
Title: Page 3.2
|
Title: Page 3.2
|
||||||
Parent: =>Page.page3
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page3
|
||||||
Sort: 2
|
Sort: 2
|
||||||
page4:
|
page4:
|
||||||
Title: Page 4
|
Title: Page 4
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\ValidationException;
|
use SilverStripe\ORM\ValidationException;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class CMSMainTest_ClassA extends Page implements TestOnly
|
class CMSMainTest_ClassA extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'CMSMainTest_ClassA';
|
private static $table_name = 'CMSMainTest_ClassA';
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\ValidationException;
|
use SilverStripe\ORM\ValidationException;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class CMSMainTest_ClassB extends Page implements TestOnly
|
class CMSMainTest_ClassB extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'CMSMainTest_ClassB';
|
private static $table_name = 'CMSMainTest_ClassB';
|
||||||
|
|
||||||
|
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\HiddenClass;
|
use SilverStripe\ORM\HiddenClass;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class CMSMainTest_HiddenClass extends Page implements TestOnly, HiddenClass
|
class CMSMainTest_HiddenClass extends SiteTree implements TestOnly, HiddenClass
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class CMSMainTest_NotRoot extends Page implements TestOnly
|
class CMSMainTest_NotRoot extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'CMSMainTest_NotRoot';
|
private static $table_name = 'CMSMainTest_NotRoot';
|
||||||
|
|
||||||
|
@ -1,219 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Controllers\CMSPageHistoryController;
|
|
||||||
use SilverStripe\CMS\Tests\Controllers\CMSPageHistoryControllerTest\HistoryController;
|
|
||||||
use SilverStripe\Control\Controller;
|
|
||||||
use SilverStripe\Core\Injector\Injector;
|
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
|
||||||
use SilverStripe\Forms\FieldGroup;
|
|
||||||
use SilverStripe\Forms\FieldList;
|
|
||||||
use SilverStripe\Forms\HiddenField;
|
|
||||||
use SilverStripe\Forms\HTMLReadonlyField;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\Forms\TextField;
|
|
||||||
|
|
||||||
class CMSPageHistoryControllerTest extends FunctionalTest
|
|
||||||
{
|
|
||||||
protected static $fixture_file = 'CMSPageHistoryControllerTest.yml';
|
|
||||||
|
|
||||||
protected $versionUnpublishedCheck;
|
|
||||||
protected $versionPublishCheck;
|
|
||||||
protected $versionUnpublishedCheck2;
|
|
||||||
protected $versionPublishCheck2;
|
|
||||||
protected $page;
|
|
||||||
|
|
||||||
protected static $extra_controllers = [
|
|
||||||
CMSPageHistoryControllerTest\HistoryController::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Deprecation::withNoReplacement(function () {
|
|
||||||
Injector::inst()->registerService(
|
|
||||||
new CMSPageHistoryController(),
|
|
||||||
CMSPageHistoryController::class
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->loginWithPermission('ADMIN');
|
|
||||||
|
|
||||||
// creates a series of published, unpublished versions of a page
|
|
||||||
$this->page = new Page();
|
|
||||||
$this->page->URLSegment = "test";
|
|
||||||
$this->page->Content = "new content";
|
|
||||||
$this->page->write();
|
|
||||||
$this->versionUnpublishedCheck = $this->page->Version; // v1
|
|
||||||
|
|
||||||
$this->page->Content = "some further content";
|
|
||||||
$this->page->publishSingle();
|
|
||||||
$this->versionPublishCheck = $this->page->Version; // v2
|
|
||||||
|
|
||||||
$this->page->Content = "No, more changes please";
|
|
||||||
$this->page->Title = "Changing titles too";
|
|
||||||
$this->page->write();
|
|
||||||
$this->versionUnpublishedCheck2 = $this->page->Version; // v3
|
|
||||||
|
|
||||||
$this->page->Title = "Final Change";
|
|
||||||
$this->page->publishSingle();
|
|
||||||
$this->versionPublishCheck2 = $this->page->Version; // v4
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetEditForm()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$controller = new CMSPageHistoryController();
|
|
||||||
$controller->setRequest(Controller::curr()->getRequest());
|
|
||||||
|
|
||||||
// should get the latest version which we cannot rollback to
|
|
||||||
$form = $controller->getEditForm($this->page->ID);
|
|
||||||
|
|
||||||
$this->assertTrue($form->Actions()->dataFieldByName('action_doRollback')->isReadonly());
|
|
||||||
|
|
||||||
$this->assertEquals($this->page->ID, $form->Fields()->dataFieldByName('ID')->Value());
|
|
||||||
$this->assertEquals($this->versionPublishCheck2, $form->Fields()->dataFieldByName('Version')->Value());
|
|
||||||
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
'Currently viewing the latest version',
|
|
||||||
$form->Fields()->fieldByName('Root.Main.CurrentlyViewingMessage')->getContent()
|
|
||||||
);
|
|
||||||
|
|
||||||
// edit form with a given version
|
|
||||||
$form = $controller->getEditForm($this->page->ID, null, $this->versionPublishCheck);
|
|
||||||
$this->assertFalse($form->Actions()->dataFieldByName('action_doRollback')->isReadonly());
|
|
||||||
|
|
||||||
$this->assertEquals($this->page->ID, $form->Fields()->dataFieldByName('ID')->Value());
|
|
||||||
$this->assertEquals($this->versionPublishCheck, $form->Fields()->dataFieldByName('Version')->Value());
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
sprintf("Currently viewing version %s.", $this->versionPublishCheck),
|
|
||||||
$form->Fields()->fieldByName('Root.Main.CurrentlyViewingMessage')->getContent()
|
|
||||||
);
|
|
||||||
|
|
||||||
// check that compare mode updates the message
|
|
||||||
$form = $controller->getEditForm($this->page->ID, null, $this->versionPublishCheck, $this->versionPublishCheck2);
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
sprintf("Comparing versions %s", $this->versionPublishCheck),
|
|
||||||
$form->Fields()->fieldByName('Root.Main.CurrentlyViewingMessage')->getContent()
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
sprintf("and %s", $this->versionPublishCheck2),
|
|
||||||
$form->Fields()->fieldByName('Root.Main.CurrentlyViewingMessage')->getContent()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo should be less tied to cms theme.
|
|
||||||
* @todo check highlighting for comparing pages.
|
|
||||||
*/
|
|
||||||
public function testVersionsForm()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$this->get('admin/pages/legacyhistory/show/' . $this->page->ID);
|
|
||||||
|
|
||||||
$form = $this->cssParser()->getBySelector('#Form_VersionsForm');
|
|
||||||
|
|
||||||
$this->assertEquals(1, count($form ?? []));
|
|
||||||
|
|
||||||
// check the page ID is present
|
|
||||||
$hidden = $form[0]->xpath("fieldset/input[@type='hidden']");
|
|
||||||
|
|
||||||
$this->assertThat($hidden, $this->logicalNot($this->isNull()), 'Hidden ID field exists');
|
|
||||||
$this->assertEquals($this->page->ID, (int) $hidden[0]->attributes()->value);
|
|
||||||
|
|
||||||
// ensure that all the versions are present in the table and displayed
|
|
||||||
$rows = $form[0]->xpath("fieldset/table/tbody/tr");
|
|
||||||
$this->assertEquals(4, count($rows ?? []));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testVersionsFormTableContainsInformation()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$this->get('admin/pages/legacyhistory/show/' . $this->page->ID);
|
|
||||||
$form = $this->cssParser()->getBySelector('#Form_VersionsForm');
|
|
||||||
$rows = $form[0]->xpath("fieldset/table/tbody/tr");
|
|
||||||
|
|
||||||
$expected = [
|
|
||||||
['version' => $this->versionPublishCheck2, 'status' => 'published'],
|
|
||||||
['version' => $this->versionUnpublishedCheck2, 'status' => 'internal'],
|
|
||||||
['version' => $this->versionPublishCheck, 'status' => 'published'],
|
|
||||||
['version' => $this->versionUnpublishedCheck, 'status' => 'internal']
|
|
||||||
];
|
|
||||||
|
|
||||||
// goes the reverse order that we created in setUp()
|
|
||||||
$i = 0;
|
|
||||||
foreach ($rows as $tr) {
|
|
||||||
// data-link must be present for the javascript to load new
|
|
||||||
$this->assertStringContainsString($expected[$i]['status'], (string) $tr->attributes()->class);
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test highlighting
|
|
||||||
$this->assertStringContainsString('active', (string) $rows[0]->attributes()->class);
|
|
||||||
$this->assertThat((string) $rows[1]->attributes()->class, $this->logicalNot($this->stringContains('active')));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testVersionsFormSelectsUnpublishedCheckbox()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$this->get('admin/pages/legacyhistory/show/' . $this->page->ID);
|
|
||||||
$checkbox = $this->cssParser()->getBySelector('#Form_VersionsForm_ShowUnpublished');
|
|
||||||
|
|
||||||
$this->assertThat($checkbox[0], $this->logicalNot($this->isNull()));
|
|
||||||
$checked = $checkbox[0]->attributes()->checked ?: '';
|
|
||||||
|
|
||||||
$this->assertThat($checked, $this->logicalNot($this->stringContains('checked')));
|
|
||||||
|
|
||||||
// viewing an unpublished
|
|
||||||
$this->get('admin/pages/legacyhistory/show/' . $this->page->ID . '/' . $this->versionUnpublishedCheck);
|
|
||||||
$checkbox = $this->cssParser()->getBySelector('#Form_VersionsForm_ShowUnpublished');
|
|
||||||
|
|
||||||
$this->assertThat($checkbox[0], $this->logicalNot($this->isNull()));
|
|
||||||
$this->assertEquals('checked', (string) $checkbox[0]->attributes()->checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTransformReadonly()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
/** @var CMSPageHistoryController $history */
|
|
||||||
$history = new CMSPageHistoryController();
|
|
||||||
$history->setRequest(Controller::curr()->getRequest());
|
|
||||||
|
|
||||||
$fieldList = FieldList::create([
|
|
||||||
FieldGroup::create('group', [
|
|
||||||
TextField::create('childField', 'child field'),
|
|
||||||
]),
|
|
||||||
TextField::create('field', 'field', 'My <del>value</del><ins>change</ins>'),
|
|
||||||
HiddenField::create('hiddenField', 'hidden field'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$newList = $history->transformReadonly($fieldList);
|
|
||||||
|
|
||||||
$field = $newList->dataFieldByName('field');
|
|
||||||
$this->assertTrue($field instanceof HTMLReadonlyField);
|
|
||||||
$this->assertStringContainsString('<ins>', $field->forTemplate());
|
|
||||||
|
|
||||||
$groupField = $newList->fieldByName('group');
|
|
||||||
$this->assertTrue($groupField instanceof FieldGroup);
|
|
||||||
|
|
||||||
$childField = $newList->dataFieldByName('childField');
|
|
||||||
$this->assertTrue($childField instanceof HTMLReadonlyField);
|
|
||||||
|
|
||||||
$hiddenField = $newList->dataFieldByName('hiddenField');
|
|
||||||
$this->assertTrue($hiddenField instanceof HiddenField);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
Page:
|
|
||||||
page1:
|
|
||||||
Title: Page 1
|
|
||||||
Sort: 1
|
|
||||||
page2:
|
|
||||||
Title: Page 2
|
|
||||||
Sort: 2
|
|
||||||
page3:
|
|
||||||
Title: Page 3
|
|
||||||
Sort: 3
|
|
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers\CMSPageHistoryControllerTest;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Controllers\CMSPageHistoryController;
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to circumvent potential URL conflicts with the silverstripe/versioned-admin history viewer controller
|
|
||||||
* when running unit tests on the legacy CMSPageHistoryController.
|
|
||||||
*/
|
|
||||||
class HistoryController extends CMSPageHistoryController implements TestOnly
|
|
||||||
{
|
|
||||||
private static $url_segment = 'pages/legacyhistory';
|
|
||||||
}
|
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search;
|
use SilverStripe\CMS\Controllers\CMSSiteTreeFilter_Search;
|
||||||
@ -15,13 +14,12 @@ use SilverStripe\Dev\SapphireTest;
|
|||||||
|
|
||||||
class CMSSiteTreeFilterTest extends SapphireTest
|
class CMSSiteTreeFilterTest extends SapphireTest
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $fixture_file = 'CMSSiteTreeFilterTest.yml';
|
protected static $fixture_file = 'CMSSiteTreeFilterTest.yml';
|
||||||
|
|
||||||
public function testSearchFilterEmpty()
|
public function testSearchFilterEmpty()
|
||||||
{
|
{
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
|
|
||||||
$f = new CMSSiteTreeFilter_Search();
|
$f = new CMSSiteTreeFilter_Search();
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
@ -32,8 +30,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testSearchFilterByTitle()
|
public function testSearchFilterByTitle()
|
||||||
{
|
{
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
|
|
||||||
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 1']);
|
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 1']);
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
@ -49,7 +47,7 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testUrlSegmentFilter()
|
public function testUrlSegmentFilter()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'page8');
|
$page = $this->objFromFixture(SiteTree::class, 'page8');
|
||||||
|
|
||||||
$filter = CMSSiteTreeFilter_Search::create(['Term' => 'lake-wanaka+adventure']);
|
$filter = CMSSiteTreeFilter_Search::create(['Term' => 'lake-wanaka+adventure']);
|
||||||
$this->assertTrue($filter->isPageIncluded($page));
|
$this->assertTrue($filter->isPageIncluded($page));
|
||||||
@ -60,8 +58,8 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testIncludesParentsForNestedMatches()
|
public function testIncludesParentsForNestedMatches()
|
||||||
{
|
{
|
||||||
$parent = $this->objFromFixture('Page', 'page3');
|
$parent = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$child = $this->objFromFixture('Page', 'page3b');
|
$child = $this->objFromFixture(SiteTree::class, 'page3b');
|
||||||
|
|
||||||
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 3b']);
|
$f = new CMSSiteTreeFilter_Search(['Title' => 'Page 3b']);
|
||||||
$results = $f->pagesIncluded();
|
$results = $f->pagesIncluded();
|
||||||
@ -78,11 +76,11 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
public function testChangedPagesFilter()
|
public function testChangedPagesFilter()
|
||||||
{
|
{
|
||||||
/** @var Page $unchangedPage */
|
/** @var Page $unchangedPage */
|
||||||
$unchangedPage = $this->objFromFixture('Page', 'page1');
|
$unchangedPage = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$unchangedPage->publishRecursive();
|
$unchangedPage->publishRecursive();
|
||||||
|
|
||||||
/** @var Page $changedPage */
|
/** @var Page $changedPage */
|
||||||
$changedPage = $this->objFromFixture('Page', 'page2');
|
$changedPage = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
$changedPage->Title = 'Original';
|
$changedPage->Title = 'Original';
|
||||||
$changedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$changedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
$changedPage->Title = 'Changed';
|
$changedPage->Title = 'Changed';
|
||||||
@ -121,7 +119,7 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testDeletedPagesFilter()
|
public function testDeletedPagesFilter()
|
||||||
{
|
{
|
||||||
$deletedPage = $this->objFromFixture('Page', 'page2');
|
$deletedPage = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
$deletedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$deletedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
$deletedPageID = $deletedPage->ID;
|
$deletedPageID = $deletedPage->ID;
|
||||||
$deletedPage->delete();
|
$deletedPage->delete();
|
||||||
@ -141,7 +139,7 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testStatusDraftPagesFilter()
|
public function testStatusDraftPagesFilter()
|
||||||
{
|
{
|
||||||
$draftPage = $this->objFromFixture('Page', 'page4');
|
$draftPage = $this->objFromFixture(SiteTree::class, 'page4');
|
||||||
$draftPage = Versioned::get_one_by_stage(
|
$draftPage = Versioned::get_one_by_stage(
|
||||||
SiteTree::class,
|
SiteTree::class,
|
||||||
'Stage',
|
'Stage',
|
||||||
@ -164,20 +162,23 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testDateFromToLastSameDate()
|
public function testDateFromToLastSameDate()
|
||||||
{
|
{
|
||||||
$draftPage = $this->objFromFixture('Page', 'page4');
|
$draftPage = $this->objFromFixture(SiteTree::class, 'page4');
|
||||||
// Grab the date
|
// Grab the date
|
||||||
$date = substr($draftPage->LastEdited ?? '', 0, 10);
|
$date = substr($draftPage->LastEdited ?? '', 0, 10);
|
||||||
// Filter with that date
|
// Filter with that date
|
||||||
$filter = new CMSSiteTreeFilter_Search([
|
$filter = new CMSSiteTreeFilter_Search([
|
||||||
'LastEditedFrom' => $date,
|
'LastEditedFrom' => $date,
|
||||||
'LastEditedTo' => $date
|
'LastEditedTo' => $date,
|
||||||
]);
|
]);
|
||||||
$this->assertTrue($filter->isPageIncluded($draftPage), 'Using the same date for from and to should show find that page');
|
$this->assertTrue(
|
||||||
|
$filter->isPageIncluded($draftPage),
|
||||||
|
'Using the same date for from and to should show find that page'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testStatusRemovedFromDraftFilter()
|
public function testStatusRemovedFromDraftFilter()
|
||||||
{
|
{
|
||||||
$removedDraftPage = $this->objFromFixture('Page', 'page6');
|
$removedDraftPage = $this->objFromFixture(SiteTree::class, 'page6');
|
||||||
$removedDraftPage->publishRecursive();
|
$removedDraftPage->publishRecursive();
|
||||||
$removedDraftPage->deleteFromStage('Stage');
|
$removedDraftPage->deleteFromStage('Stage');
|
||||||
$removedDraftPage = Versioned::get_one_by_stage(
|
$removedDraftPage = Versioned::get_one_by_stage(
|
||||||
@ -202,7 +203,7 @@ class CMSSiteTreeFilterTest extends SapphireTest
|
|||||||
|
|
||||||
public function testStatusDeletedFilter()
|
public function testStatusDeletedFilter()
|
||||||
{
|
{
|
||||||
$deletedPage = $this->objFromFixture('Page', 'page7');
|
$deletedPage = $this->objFromFixture(SiteTree::class, 'page7');
|
||||||
$deletedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$deletedPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
$deletedPageID = $deletedPage->ID;
|
$deletedPageID = $deletedPage->ID;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
page1:
|
page1:
|
||||||
Title: Page 1
|
Title: Page 1
|
||||||
page2:
|
page2:
|
||||||
@ -15,19 +15,19 @@ Page:
|
|||||||
page7:
|
page7:
|
||||||
Title: Page 7
|
Title: Page 7
|
||||||
page7a:
|
page7a:
|
||||||
Parent: =>Page.page7
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page7
|
||||||
Title: Page 7a
|
Title: Page 7a
|
||||||
page2a:
|
page2a:
|
||||||
Parent: =>Page.page2
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page2
|
||||||
Title: Page 2a
|
Title: Page 2a
|
||||||
page2b:
|
page2b:
|
||||||
Parent: =>Page.page2
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page2
|
||||||
Title: Page 2b
|
Title: Page 2b
|
||||||
page3a:
|
page3a:
|
||||||
Parent: =>Page.page3
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page3
|
||||||
Title: Page 3a
|
Title: Page 3a
|
||||||
page3b:
|
page3b:
|
||||||
Parent: =>Page.page3
|
Parent: =>SilverStripe\CMS\Model\SiteTree.page3
|
||||||
Title: Page 3b
|
Title: Page 3b
|
||||||
page8:
|
page8:
|
||||||
Title: EncodedUrlSegment
|
Title: EncodedUrlSegment
|
||||||
|
@ -32,7 +32,7 @@ class CMSTreeTest extends FunctionalTest
|
|||||||
$data = [
|
$data = [
|
||||||
'SiblingIDs' => $siblingIDs,
|
'SiblingIDs' => $siblingIDs,
|
||||||
'ID' => $page2->ID,
|
'ID' => $page2->ID,
|
||||||
'ParentID' => 0
|
'ParentID' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = $this->post('admin/pages/edit/savetreenode', $data);
|
$response = $this->post('admin/pages/edit/savetreenode', $data);
|
||||||
@ -62,12 +62,12 @@ class CMSTreeTest extends FunctionalTest
|
|||||||
$siblingIDs = [
|
$siblingIDs = [
|
||||||
$page31->ID,
|
$page31->ID,
|
||||||
$page2->ID,
|
$page2->ID,
|
||||||
$page32->ID
|
$page32->ID,
|
||||||
];
|
];
|
||||||
$data = [
|
$data = [
|
||||||
'SiblingIDs' => $siblingIDs,
|
'SiblingIDs' => $siblingIDs,
|
||||||
'ID' => $page2->ID,
|
'ID' => $page2->ID,
|
||||||
'ParentID' => $page3->ID
|
'ParentID' => $page3->ID,
|
||||||
];
|
];
|
||||||
$response = $this->post('admin/pages/edit/savetreenode', $data);
|
$response = $this->post('admin/pages/edit/savetreenode', $data);
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
@ -95,7 +95,7 @@ class CMSTreeTest extends FunctionalTest
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
// Check page
|
// Check page
|
||||||
$result = $this->get('admin/pages/edit/updatetreenodes?ids='.$page1->ID);
|
$result = $this->get('admin/pages/edit/updatetreenodes?ids=' . $page1->ID);
|
||||||
$this->assertEquals(200, $result->getStatusCode());
|
$this->assertEquals(200, $result->getStatusCode());
|
||||||
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
||||||
$data = json_decode($result->getBody() ?? '', true);
|
$data = json_decode($result->getBody() ?? '', true);
|
||||||
@ -105,7 +105,7 @@ class CMSTreeTest extends FunctionalTest
|
|||||||
$this->assertEmpty($pageData['PrevID']);
|
$this->assertEmpty($pageData['PrevID']);
|
||||||
|
|
||||||
// check subpage
|
// check subpage
|
||||||
$result = $this->get('admin/pages/edit/updatetreenodes?ids='.$page31->ID);
|
$result = $this->get('admin/pages/edit/updatetreenodes?ids=' . $page31->ID);
|
||||||
$this->assertEquals(200, $result->getStatusCode());
|
$this->assertEquals(200, $result->getStatusCode());
|
||||||
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
||||||
$data = json_decode($result->getBody() ?? '', true);
|
$data = json_decode($result->getBody() ?? '', true);
|
||||||
@ -115,7 +115,7 @@ class CMSTreeTest extends FunctionalTest
|
|||||||
$this->assertEmpty($pageData['PrevID']);
|
$this->assertEmpty($pageData['PrevID']);
|
||||||
|
|
||||||
// Multiple pages
|
// Multiple pages
|
||||||
$result = $this->get('admin/pages/edit/updatetreenodes?ids='.$page1->ID.','.$page2->ID);
|
$result = $this->get('admin/pages/edit/updatetreenodes?ids=' . $page1->ID . ',' . $page2->ID);
|
||||||
$this->assertEquals(200, $result->getStatusCode());
|
$this->assertEquals(200, $result->getStatusCode());
|
||||||
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
$this->assertEquals('application/json', $result->getHeader('Content-Type'));
|
||||||
$data = json_decode($result->getBody() ?? '', true);
|
$data = json_decode($result->getBody() ?? '', true);
|
||||||
|
@ -6,7 +6,7 @@ use SilverStripe\Versioned\Versioned;
|
|||||||
use SilverStripe\Control\HTTPResponse_Exception;
|
use SilverStripe\Control\HTTPResponse_Exception;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
use SilverStripe\Dev\FunctionalTest;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class ContentControllerPermissionsTest extends FunctionalTest
|
class ContentControllerPermissionsTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
@ -17,7 +17,7 @@ class ContentControllerPermissionsTest extends FunctionalTest
|
|||||||
public function testCanViewStage()
|
public function testCanViewStage()
|
||||||
{
|
{
|
||||||
// Create a new page
|
// Create a new page
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->URLSegment = 'testpage';
|
$page->URLSegment = 'testpage';
|
||||||
$page->write();
|
$page->write();
|
||||||
$page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
@ -38,7 +38,11 @@ class ContentControllerPermissionsTest extends FunctionalTest
|
|||||||
$response = $responseException->getResponse();
|
$response = $responseException->getResponse();
|
||||||
}
|
}
|
||||||
// should redirect to login
|
// should redirect to login
|
||||||
$this->assertEquals($response->getStatusCode(), 302, 'Redirects to login page when not logged in for draft stage');
|
$this->assertEquals(
|
||||||
|
$response->getStatusCode(),
|
||||||
|
302,
|
||||||
|
'Redirects to login page when not logged in for draft stage'
|
||||||
|
);
|
||||||
$this->assertStringContainsString(
|
$this->assertStringContainsString(
|
||||||
Config::inst()->get('SilverStripe\\Security\\Security', 'login_url'),
|
Config::inst()->get('SilverStripe\\Security\\Security', 'login_url'),
|
||||||
$response->getHeader('Location')
|
$response->getHeader('Location')
|
||||||
@ -47,6 +51,10 @@ class ContentControllerPermissionsTest extends FunctionalTest
|
|||||||
$this->logInWithPermission('CMS_ACCESS_CMSMain');
|
$this->logInWithPermission('CMS_ACCESS_CMSMain');
|
||||||
|
|
||||||
$response = $this->get('/testpage/?stage=Stage');
|
$response = $this->get('/testpage/?stage=Stage');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Doesnt redirect to login, but shows page for authenticated user');
|
$this->assertEquals(
|
||||||
|
$response->getStatusCode(),
|
||||||
|
200,
|
||||||
|
'Doesnt redirect to login, but shows page for authenticated user'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,23 @@ namespace SilverStripe\CMS\Tests\Controllers;
|
|||||||
|
|
||||||
use SilverStripe\Assets\File;
|
use SilverStripe\Assets\File;
|
||||||
use SilverStripe\CMS\Controllers\ContentController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\CMS\Search\ContentControllerSearchExtension;
|
use SilverStripe\CMS\Search\ContentControllerSearchExtension;
|
||||||
use SilverStripe\Dev\SapphireTest;
|
use SilverStripe\Dev\SapphireTest;
|
||||||
use SilverStripe\ORM\Search\FulltextSearchable;
|
use SilverStripe\ORM\Search\FulltextSearchable;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class ContentControllerSearchExtensionTest extends SapphireTest
|
class ContentControllerSearchExtensionTest extends SapphireTest
|
||||||
{
|
{
|
||||||
protected static $required_extensions = [
|
protected static $required_extensions = [
|
||||||
ContentController::class => [
|
ContentController::class => [
|
||||||
ContentControllerSearchExtension::class,
|
ContentControllerSearchExtension::class,
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
public function testCustomSearchFormClassesToTest()
|
public function testCustomSearchFormClassesToTest()
|
||||||
{
|
{
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->URLSegment = 'whatever';
|
$page->URLSegment = 'whatever';
|
||||||
$page->Content = 'oh really?';
|
$page->Content = 'oh really?';
|
||||||
$page->write();
|
$page->write();
|
||||||
|
10
tests/php/Controllers/ContentControllerTest.php
Executable file → Normal file
10
tests/php/Controllers/ContentControllerTest.php
Executable file → Normal file
@ -10,7 +10,6 @@ use SilverStripe\Control\HTTPResponse_Exception;
|
|||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
use SilverStripe\Dev\FunctionalTest;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class ContentControllerTest extends FunctionalTest
|
class ContentControllerTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
@ -31,8 +30,8 @@ class ContentControllerTest extends FunctionalTest
|
|||||||
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
||||||
|
|
||||||
// Ensure all pages are published
|
// Ensure all pages are published
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
foreach (Page::get() as $page) {
|
foreach (SiteTree::get() as $page) {
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,8 +94,7 @@ class ContentControllerTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testDeepNestedURLs()
|
public function testDeepNestedURLs()
|
||||||
{
|
{
|
||||||
|
$page = new SiteTree();
|
||||||
$page = new Page();
|
|
||||||
$page->URLSegment = 'base-page';
|
$page->URLSegment = 'base-page';
|
||||||
$page->write();
|
$page->write();
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
@ -174,7 +172,7 @@ class ContentControllerTest extends FunctionalTest
|
|||||||
$response = $this->get($page->RelativeLink());
|
$response = $this->get($page->RelativeLink());
|
||||||
$this->assertEquals("ContentControllerTestPageWithoutController", trim($response->getBody() ?? ''));
|
$this->assertEquals("ContentControllerTestPageWithoutController", trim($response->getBody() ?? ''));
|
||||||
|
|
||||||
// // This should fall over to user Page.ss
|
// This should fall over to user Page.ss
|
||||||
$page = new ContentControllerTestPage();
|
$page = new ContentControllerTestPage();
|
||||||
$page->URLSegment = "test";
|
$page->URLSegment = "test";
|
||||||
$page->write();
|
$page->write();
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class ContentControllerTestPage extends Page implements TestOnly
|
class ContentControllerTestPage extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'ContentControllerTestPage';
|
private static $table_name = 'ContentControllerTestPage';
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ class ContentControllerTestPageController extends PageController implements Test
|
|||||||
{
|
{
|
||||||
private static $allowed_actions = [
|
private static $allowed_actions = [
|
||||||
'test',
|
'test',
|
||||||
'testwithouttemplate'
|
'testwithouttemplate',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function testwithouttemplate()
|
public function testwithouttemplate()
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class ContentControllerTestPageWithoutController extends Page implements TestOnly
|
class ContentControllerTestPageWithoutController extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
|
||||||
|
|
||||||
class ContentControllerTest_Page extends Page implements TestOnly
|
class ContentControllerTest_Page extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'ContentControllerTest_Page';
|
private static $table_name = 'ContentControllerTest_Page';
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
namespace SilverStripe\CMS\Tests\Controllers;
|
||||||
|
|
||||||
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use PageController;
|
|
||||||
|
|
||||||
class ContentControllerTest_PageController extends PageController implements TestOnly
|
class ContentControllerTest_PageController extends ContentController implements TestOnly
|
||||||
{
|
{
|
||||||
|
|
||||||
private static $allowed_actions = [
|
private static $allowed_actions = [
|
||||||
'second_index'
|
'second_index',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
|
@ -10,7 +10,6 @@ use SilverStripe\Core\Config\Config;
|
|||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
use SilverStripe\Dev\FunctionalTest;
|
||||||
use Page;
|
|
||||||
use SilverStripe\View\Parsers\URLSegmentFilter;
|
use SilverStripe\View\Parsers\URLSegmentFilter;
|
||||||
|
|
||||||
class ModelAsControllerTest extends FunctionalTest
|
class ModelAsControllerTest extends FunctionalTest
|
||||||
@ -34,7 +33,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
|
|
||||||
protected function generateNestedPagesFixture()
|
protected function generateNestedPagesFixture()
|
||||||
{
|
{
|
||||||
$level1 = new Page();
|
$level1 = new SiteTree();
|
||||||
$level1->Title = 'First Level';
|
$level1->Title = 'First Level';
|
||||||
$level1->URLSegment = 'level1';
|
$level1->URLSegment = 'level1';
|
||||||
$level1->write();
|
$level1->write();
|
||||||
@ -44,7 +43,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$level1->write();
|
$level1->write();
|
||||||
$level1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$level1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$level2 = new Page();
|
$level2 = new SiteTree();
|
||||||
$level2->Title = 'Second Level';
|
$level2->Title = 'Second Level';
|
||||||
$level2->URLSegment = 'level2';
|
$level2->URLSegment = 'level2';
|
||||||
$level2->ParentID = $level1->ID;
|
$level2->ParentID = $level1->ID;
|
||||||
@ -55,7 +54,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$level2->write();
|
$level2->write();
|
||||||
$level2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$level2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$level3 = new Page();
|
$level3 = new SiteTree();
|
||||||
$level3->Title = "Level 3";
|
$level3->Title = "Level 3";
|
||||||
$level3->URLSegment = 'level3';
|
$level3->URLSegment = 'level3';
|
||||||
$level3->ParentID = $level2->ID;
|
$level3->ParentID = $level2->ID;
|
||||||
@ -93,7 +92,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$response = $this->get('newlevel1/level2');
|
$response = $this->get('newlevel1/level2');
|
||||||
$this->assertEquals($response->getStatusCode(), 301);
|
$this->assertEquals($response->getStatusCode(), 301);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/'),
|
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2'),
|
||||||
$response->getHeader('Location')
|
$response->getHeader('Location')
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$response = $this->get('newlevel1/newlevel2/level3');
|
$response = $this->get('newlevel1/newlevel2/level3');
|
||||||
$this->assertEquals($response->getStatusCode(), 301);
|
$this->assertEquals($response->getStatusCode(), 301);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3/'),
|
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3'),
|
||||||
$response->getHeader('Location')
|
$response->getHeader('Location')
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -115,7 +114,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
*/
|
*/
|
||||||
public function testHeavilyNestedRenamedRedirectedPages()
|
public function testHeavilyNestedRenamedRedirectedPages()
|
||||||
{
|
{
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->Title = 'First Level';
|
$page->Title = 'First Level';
|
||||||
$page->URLSegment = 'oldurl';
|
$page->URLSegment = 'oldurl';
|
||||||
$page->write();
|
$page->write();
|
||||||
@ -125,28 +124,28 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$page->write();
|
$page->write();
|
||||||
$page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$page2 = new Page();
|
$page2 = new SiteTree();
|
||||||
$page2->Title = 'Second Level Page';
|
$page2->Title = 'Second Level Page';
|
||||||
$page2->URLSegment = 'level2';
|
$page2->URLSegment = 'level2';
|
||||||
$page2->ParentID = $page->ID;
|
$page2->ParentID = $page->ID;
|
||||||
$page2->write();
|
$page2->write();
|
||||||
$page2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page2->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$page3 = new Page();
|
$page3 = new SiteTree();
|
||||||
$page3->Title = 'Third Level Page';
|
$page3->Title = 'Third Level Page';
|
||||||
$page3->URLSegment = 'level3';
|
$page3->URLSegment = 'level3';
|
||||||
$page3->ParentID = $page2->ID;
|
$page3->ParentID = $page2->ID;
|
||||||
$page3->write();
|
$page3->write();
|
||||||
$page3->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page3->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$page4 = new Page();
|
$page4 = new SiteTree();
|
||||||
$page4->Title = 'Fourth Level Page';
|
$page4->Title = 'Fourth Level Page';
|
||||||
$page4->URLSegment = 'level4';
|
$page4->URLSegment = 'level4';
|
||||||
$page4->ParentID = $page3->ID;
|
$page4->ParentID = $page3->ID;
|
||||||
$page4->write();
|
$page4->write();
|
||||||
$page4->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page4->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$page5 = new Page();
|
$page5 = new SiteTree();
|
||||||
$page5->Title = 'Fifth Level Page';
|
$page5->Title = 'Fifth Level Page';
|
||||||
$page5->URLSegment = 'level5';
|
$page5->URLSegment = 'level5';
|
||||||
$page5->ParentID = $page4->ID;
|
$page5->ParentID = $page4->ID;
|
||||||
@ -154,10 +153,10 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$page5->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$page5->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
// Test that the redirect still works fine when trying to access the most nested page
|
// Test that the redirect still works fine when trying to access the most nested page
|
||||||
$response = $this->get('oldurl/level2/level3/level4/level5/');
|
$response = $this->get('oldurl/level2/level3/level4/level5');
|
||||||
$this->assertEquals($response->getStatusCode(), 301);
|
$this->assertEquals($response->getStatusCode(), 301);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Controller::join_links(Director::baseURL() . 'newurl/level2/level3/level4/level5/'),
|
Controller::join_links(Director::baseURL() . 'newurl/level2/level3/level4/level5'),
|
||||||
$response->getHeader('Location')
|
$response->getHeader('Location')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -171,7 +170,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$response = $this->get('newlevel3');
|
$response = $this->get('newlevel3');
|
||||||
$this->assertEquals(301, $response->getStatusCode());
|
$this->assertEquals(301, $response->getStatusCode());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Director::baseURL() . 'newlevel1/newlevel2/newlevel3/',
|
Director::baseURL() . 'newlevel1/newlevel2/newlevel3',
|
||||||
$response->getHeader("Location")
|
$response->getHeader("Location")
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -179,7 +178,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$response = $this->get('level3');
|
$response = $this->get('level3');
|
||||||
$this->assertEquals(301, $response->getStatusCode());
|
$this->assertEquals(301, $response->getStatusCode());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Director::baseURL() . 'newlevel1/newlevel2/newlevel3/',
|
Director::baseURL() . 'newlevel1/newlevel2/newlevel3',
|
||||||
$response->getHeader("Location")
|
$response->getHeader("Location")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -188,8 +187,8 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
$this->generateNestedPagesFixture();
|
$this->generateNestedPagesFixture();
|
||||||
|
|
||||||
$otherParent = new Page([
|
$otherParent = new SiteTree([
|
||||||
'URLSegment' => 'otherparent'
|
'URLSegment' => 'otherparent',
|
||||||
]);
|
]);
|
||||||
$otherParent->write();
|
$otherParent->write();
|
||||||
$otherParent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$otherParent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
@ -215,10 +214,10 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$this->generateNestedPagesFixture();
|
$this->generateNestedPagesFixture();
|
||||||
|
|
||||||
// check third level URLSegment
|
// check third level URLSegment
|
||||||
$response = $this->get('newlevel1/newlevel2/level3/?foo=bar&test=test');
|
$response = $this->get('newlevel1/newlevel2/level3?foo=bar&test=test');
|
||||||
$this->assertEquals($response->getStatusCode(), 301);
|
$this->assertEquals($response->getStatusCode(), 301);
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3/', '?foo=bar&test=test'),
|
Controller::join_links(Director::baseURL() . 'newlevel1/newlevel2/newlevel3', '?foo=bar&test=test'),
|
||||||
$response->getHeader('Location')
|
$response->getHeader('Location')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -232,9 +231,9 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
$this->generateNestedPagesFixture();
|
$this->generateNestedPagesFixture();
|
||||||
|
|
||||||
$otherLevel1 = new Page([
|
$otherLevel1 = new SiteTree([
|
||||||
'Title' => "Other Level 1",
|
'Title' => "Other Level 1",
|
||||||
'URLSegment' => 'level1'
|
'URLSegment' => 'level1',
|
||||||
]);
|
]);
|
||||||
$otherLevel1->write();
|
$otherLevel1->write();
|
||||||
$otherLevel1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$otherLevel1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
@ -260,7 +259,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
*/
|
*/
|
||||||
public function testFindOldPage()
|
public function testFindOldPage()
|
||||||
{
|
{
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->Title = 'First Level';
|
$page->Title = 'First Level';
|
||||||
$page->URLSegment = 'oldurl';
|
$page->URLSegment = 'oldurl';
|
||||||
$page->write();
|
$page->write();
|
||||||
@ -274,7 +273,7 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$matchedPage = SiteTree::get_by_link($url);
|
$matchedPage = SiteTree::get_by_link($url);
|
||||||
$this->assertEquals('First Level', $matchedPage->Title);
|
$this->assertEquals('First Level', $matchedPage->Title);
|
||||||
|
|
||||||
$page2 = new Page();
|
$page2 = new SiteTree();
|
||||||
$page2->Title = 'Second Level Page';
|
$page2->Title = 'Second Level Page';
|
||||||
$page2->URLSegment = 'oldpage2';
|
$page2->URLSegment = 'oldpage2';
|
||||||
$page2->ParentID = $page->ID;
|
$page2->ParentID = $page->ID;
|
||||||
@ -304,12 +303,12 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
RootURLController::reset();
|
RootURLController::reset();
|
||||||
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
||||||
|
|
||||||
$draft = new Page();
|
$draft = new SiteTree();
|
||||||
$draft->Title = 'Root Leve Draft Page';
|
$draft->Title = 'Root Leve Draft Page';
|
||||||
$draft->URLSegment = 'root';
|
$draft->URLSegment = 'root';
|
||||||
$draft->write();
|
$draft->write();
|
||||||
|
|
||||||
$published = new Page();
|
$published = new SiteTree();
|
||||||
$published->Title = 'Published Page Under Draft Page';
|
$published->Title = 'Published Page Under Draft Page';
|
||||||
$published->URLSegment = 'sub-root';
|
$published->URLSegment = 'sub-root';
|
||||||
$published->write();
|
$published->write();
|
||||||
@ -319,7 +318,8 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$response->getStatusCode(),
|
$response->getStatusCode(),
|
||||||
404,
|
404,
|
||||||
'The page should not be found since its parent has not been published, in this case http://<yousitename>/root/sub-root or http://<yousitename>/sub-root'
|
'The page should not be found since its parent has not been published, in this case ' .
|
||||||
|
'http://<yousitename>/root/sub-root or http://<yousitename>/sub-root'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,13 +327,13 @@ class ModelAsControllerTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
Config::modify()->set(URLSegmentFilter::class, 'default_allow_multibyte', true);
|
Config::modify()->set(URLSegmentFilter::class, 'default_allow_multibyte', true);
|
||||||
|
|
||||||
$parent = new Page();
|
$parent = new SiteTree();
|
||||||
$parent->Title = 'Multibyte test';
|
$parent->Title = 'Multibyte test';
|
||||||
$parent->URLSegment = 'بلاگ';
|
$parent->URLSegment = 'بلاگ';
|
||||||
$parent->write();
|
$parent->write();
|
||||||
$parent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$parent->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$child = new Page();
|
$child = new SiteTree();
|
||||||
$child->Title = 'Multibyte test';
|
$child->Title = 'Multibyte test';
|
||||||
$child->URLSegment = 'فضة';
|
$child->URLSegment = 'فضة';
|
||||||
$child->ParentID = $parent->ID;
|
$child->ParentID = $parent->ID;
|
||||||
|
@ -13,7 +13,7 @@ class RootURLControllerTest extends SapphireTest
|
|||||||
|
|
||||||
public function testGetHomepageLink()
|
public function testGetHomepageLink()
|
||||||
{
|
{
|
||||||
$default = $this->objFromFixture('Page', 'home');
|
$default = $this->objFromFixture(SiteTree::class, 'home');
|
||||||
|
|
||||||
Config::modify()->set(SiteTree::class, 'nested_urls', false);
|
Config::modify()->set(SiteTree::class, 'nested_urls', false);
|
||||||
$this->assertEquals('home', RootURLController::get_homepage_link());
|
$this->assertEquals('home', RootURLController::get_homepage_link());
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
home:
|
home:
|
||||||
Title: Home
|
Title: Home
|
||||||
nested:
|
nested:
|
||||||
Title: Nested Home
|
Title: Nested Home
|
||||||
Parent: =>Page.home
|
Parent: =>SilverStripe\CMS\Model\SiteTree.home
|
||||||
page1:
|
page1:
|
||||||
Title: First Page
|
Title: First Page
|
||||||
URLSegment: page1
|
URLSegment: page1
|
||||||
|
@ -1,239 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigator;
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_ArchiveLink;
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_LiveLink;
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_StageLink;
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem_Unversioned;
|
|
||||||
use SilverStripe\Dev\SapphireTest;
|
|
||||||
use SilverStripe\Security\Member;
|
|
||||||
|
|
||||||
class SilverStripeNavigatorTest extends SapphireTest
|
|
||||||
{
|
|
||||||
protected static $fixture_file = 'CMSMainTest.yml';
|
|
||||||
|
|
||||||
protected static $extra_dataobjects = [
|
|
||||||
SilverStripeNavigatorTest\UnstagedRecord::class,
|
|
||||||
SilverStripeNavigatorTest\UnversionedRecord::class,
|
|
||||||
SilverStripeNavigatorTest\VersionedRecord::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
public function testGetItemsAutoDiscovery(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
$this->assertContains(
|
|
||||||
SilverStripeNavigatorTest_TestItem::class,
|
|
||||||
$classes,
|
|
||||||
'Autodiscovers new classes'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetItemsPublished(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$record->publishRecursive();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
// Has the live and staged links
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_LiveLink::class, $classes);
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_StageLink::class, $classes);
|
|
||||||
|
|
||||||
// Does not have the other links
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_ArchiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_Unversioned::class, $classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetItemsStaged(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
// Has the stage link
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_StageLink::class, $classes);
|
|
||||||
|
|
||||||
// Does not have the other links
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_ArchiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_LiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_Unversioned::class, $classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetItemsArchived(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$record->doArchive();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
// Has the archived link
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_ArchiveLink::class, $classes);
|
|
||||||
|
|
||||||
// Does not have the other links
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_LiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_StageLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_UnversionedLink::class, $classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetItemsUnstaged(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\UnstagedRecord();
|
|
||||||
$record->previewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
// Has the unversioned link
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_Unversioned::class, $classes);
|
|
||||||
|
|
||||||
// Does not have the other links
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_ArchiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_LiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_StageLink::class, $classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetItemsUnversioned(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\UnversionedRecord();
|
|
||||||
$record->previewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$navigator = new SilverStripeNavigator($record);
|
|
||||||
$classes = array_map('get_class', $navigator->getItems()->toArray());
|
|
||||||
|
|
||||||
// Has the unversioned link
|
|
||||||
$this->assertContains(SilverStripeNavigatorItem_Unversioned::class, $classes);
|
|
||||||
|
|
||||||
// Does not have the other links
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_ArchiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_LiveLink::class, $classes);
|
|
||||||
$this->assertNotContains(SilverStripeNavigatorItem_StageLink::class, $classes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanViewPublished(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->write();
|
|
||||||
$record->publishRecursive();
|
|
||||||
$liveLinkItem = new SilverStripeNavigatorItem_LiveLink($record);
|
|
||||||
$stagedLinkItem = new SilverStripeNavigatorItem_StageLink($record);
|
|
||||||
$archivedLinkItem = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
$unversionedLinkItem = new SilverStripeNavigatorItem_Unversioned($record);
|
|
||||||
|
|
||||||
// Cannot view staged and live links when there's no preview link
|
|
||||||
$this->assertFalse($liveLinkItem->canView());
|
|
||||||
$this->assertFalse($stagedLinkItem->canView());
|
|
||||||
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
$record->write();
|
|
||||||
$record->publishRecursive();
|
|
||||||
|
|
||||||
// Can view staged and live links
|
|
||||||
$this->assertTrue($liveLinkItem->canView());
|
|
||||||
$this->assertTrue($stagedLinkItem->canView());
|
|
||||||
// Cannot view the other links
|
|
||||||
$this->assertFalse($archivedLinkItem->canView());
|
|
||||||
$this->assertFalse($unversionedLinkItem->canView());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanViewStaged(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->write();
|
|
||||||
$liveLinkItem = new SilverStripeNavigatorItem_LiveLink($record);
|
|
||||||
$stagedLinkItem = new SilverStripeNavigatorItem_StageLink($record);
|
|
||||||
$archivedLinkItem = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
$unversionedLinkItem = new SilverStripeNavigatorItem_Unversioned($record);
|
|
||||||
|
|
||||||
// Cannot view staged link when there's no preview link
|
|
||||||
$this->assertFalse($stagedLinkItem->canView());
|
|
||||||
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
|
|
||||||
// Can view staged link
|
|
||||||
$this->assertTrue($stagedLinkItem->canView());
|
|
||||||
// Cannot view the other links
|
|
||||||
$this->assertFalse($liveLinkItem->canView());
|
|
||||||
$this->assertFalse($archivedLinkItem->canView());
|
|
||||||
$this->assertFalse($unversionedLinkItem->canView());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanViewArchived(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\VersionedRecord();
|
|
||||||
$record->write();
|
|
||||||
$record->doArchive();
|
|
||||||
$liveLinkItem = new SilverStripeNavigatorItem_LiveLink($record);
|
|
||||||
$stagedLinkItem = new SilverStripeNavigatorItem_StageLink($record);
|
|
||||||
$archivedLinkItem = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
$unversionedLinkItem = new SilverStripeNavigatorItem_Unversioned($record);
|
|
||||||
|
|
||||||
// Cannot view archived link when there's no preview link
|
|
||||||
$this->assertFalse($archivedLinkItem->canView());
|
|
||||||
|
|
||||||
$record->PreviewLinkTestProperty = 'some-value';
|
|
||||||
|
|
||||||
// Can view archived link
|
|
||||||
$this->assertTrue($archivedLinkItem->canView());
|
|
||||||
// Cannot view the other links
|
|
||||||
$this->assertFalse($liveLinkItem->canView());
|
|
||||||
$this->assertFalse($stagedLinkItem->canView());
|
|
||||||
$this->assertFalse($unversionedLinkItem->canView());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanViewUnstaged(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\UnstagedRecord();
|
|
||||||
$record->write();
|
|
||||||
$liveLinkItem = new SilverStripeNavigatorItem_LiveLink($record);
|
|
||||||
$stagedLinkItem = new SilverStripeNavigatorItem_StageLink($record);
|
|
||||||
$archivedLinkItem = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
$unversionedLinkItem = new SilverStripeNavigatorItem_Unversioned($record);
|
|
||||||
|
|
||||||
// Cannot view unversioned link when there's no preview link
|
|
||||||
$this->assertFalse($unversionedLinkItem->canView());
|
|
||||||
|
|
||||||
$record->previewLinkTestProperty = 'some-value';
|
|
||||||
|
|
||||||
// Can view unversioned link
|
|
||||||
$this->assertTrue($unversionedLinkItem->canView());
|
|
||||||
// Cannot view the other links
|
|
||||||
$this->assertFalse($liveLinkItem->canView());
|
|
||||||
$this->assertFalse($stagedLinkItem->canView());
|
|
||||||
$this->assertFalse($archivedLinkItem->canView());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCanViewUnversioned(): void
|
|
||||||
{
|
|
||||||
$record = new SilverStripeNavigatorTest\UnversionedRecord();
|
|
||||||
$record->write();
|
|
||||||
$liveLinkItem = new SilverStripeNavigatorItem_LiveLink($record);
|
|
||||||
$stagedLinkItem = new SilverStripeNavigatorItem_StageLink($record);
|
|
||||||
$archivedLinkItem = new SilverStripeNavigatorItem_ArchiveLink($record);
|
|
||||||
$unversionedLinkItem = new SilverStripeNavigatorItem_Unversioned($record);
|
|
||||||
|
|
||||||
// Cannot view unversioned link when there's no preview link
|
|
||||||
$this->assertFalse($unversionedLinkItem->canView());
|
|
||||||
|
|
||||||
$record->previewLinkTestProperty = 'some-value';
|
|
||||||
|
|
||||||
// Can view unversioned link
|
|
||||||
$this->assertTrue($unversionedLinkItem->canView());
|
|
||||||
// Cannot view the other links
|
|
||||||
$this->assertFalse($liveLinkItem->canView());
|
|
||||||
$this->assertFalse($stagedLinkItem->canView());
|
|
||||||
$this->assertFalse($archivedLinkItem->canView());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers\SilverStripeNavigatorTest;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Versioned but not staged
|
|
||||||
*/
|
|
||||||
class UnstagedRecord extends DataObject implements TestOnly, CMSPreviewable
|
|
||||||
{
|
|
||||||
private static $table_name = 'SilverStripeNavigatorTest_UnstagedRecord';
|
|
||||||
|
|
||||||
private static $show_stage_link = true;
|
|
||||||
|
|
||||||
private static $show_live_link = true;
|
|
||||||
|
|
||||||
private static $show_unversioned_preview_link = true;
|
|
||||||
|
|
||||||
private static $extensions = [
|
|
||||||
Versioned::class . '.versioned',
|
|
||||||
];
|
|
||||||
|
|
||||||
public $previewLinkTestProperty = null;
|
|
||||||
|
|
||||||
public function PreviewLink($action = null)
|
|
||||||
{
|
|
||||||
return $this->previewLinkTestProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To determine preview mechanism (e.g. embedded / iframe)
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMimeType()
|
|
||||||
{
|
|
||||||
return 'text/html';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CMSEditLink()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers\SilverStripeNavigatorTest;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
class UnversionedRecord extends DataObject implements TestOnly, CMSPreviewable
|
|
||||||
{
|
|
||||||
private static $table_name = 'SilverStripeNavigatorTest_UnversionedRecord';
|
|
||||||
|
|
||||||
private static $show_stage_link = true;
|
|
||||||
|
|
||||||
private static $show_live_link = true;
|
|
||||||
|
|
||||||
private static $show_unversioned_preview_link = true;
|
|
||||||
|
|
||||||
public $previewLinkTestProperty = null;
|
|
||||||
|
|
||||||
public function PreviewLink($action = null)
|
|
||||||
{
|
|
||||||
return $this->previewLinkTestProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMimeType()
|
|
||||||
{
|
|
||||||
return 'text/html';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CMSEditLink()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers\SilverStripeNavigatorTest;
|
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
|
||||||
use SilverStripe\ORM\CMSPreviewable;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
|
|
||||||
class VersionedRecord extends DataObject implements TestOnly, CMSPreviewable
|
|
||||||
{
|
|
||||||
private static $table_name = 'SilverStripeNavigatorTest_VersionedRecord';
|
|
||||||
|
|
||||||
private static $show_stage_link = true;
|
|
||||||
|
|
||||||
private static $show_live_link = true;
|
|
||||||
|
|
||||||
private static $show_unversioned_preview_link = true;
|
|
||||||
|
|
||||||
private static $db = [
|
|
||||||
'PreviewLinkTestProperty' => 'Text',
|
|
||||||
];
|
|
||||||
|
|
||||||
private static $extensions = [
|
|
||||||
Versioned::class,
|
|
||||||
];
|
|
||||||
|
|
||||||
public function PreviewLink($action = null)
|
|
||||||
{
|
|
||||||
return $this->PreviewLinkTestProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMimeType()
|
|
||||||
{
|
|
||||||
return 'text/html';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function CMSEditLink()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Controllers;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Controllers\SilverStripeNavigatorItem;
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
|
||||||
|
|
||||||
class SilverStripeNavigatorTest_TestItem extends SilverStripeNavigatorItem implements TestOnly
|
|
||||||
{
|
|
||||||
public function getTitle()
|
|
||||||
{
|
|
||||||
return self::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHTML()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -44,7 +44,7 @@ class LinkablePluginTest extends SapphireTest
|
|||||||
|
|
||||||
public function testResolver()
|
public function testResolver()
|
||||||
{
|
{
|
||||||
$page = SiteTree::create([
|
$page = new SiteTree([
|
||||||
'Title' => 'Test page',
|
'Title' => 'Test page',
|
||||||
'URLSegment' => 'test-page',
|
'URLSegment' => 'test-page',
|
||||||
'ParentID' => 0,
|
'ParentID' => 0,
|
||||||
@ -52,7 +52,7 @@ class LinkablePluginTest extends SapphireTest
|
|||||||
$page->write();
|
$page->write();
|
||||||
$page->publishRecursive();
|
$page->publishRecursive();
|
||||||
|
|
||||||
$page = SiteTree::create([
|
$page = new SiteTree([
|
||||||
'Title' => 'Other test page',
|
'Title' => 'Other test page',
|
||||||
'URLSegment' => 'other-test-page',
|
'URLSegment' => 'other-test-page',
|
||||||
'ParentID' => 0,
|
'ParentID' => 0,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\RedirectorPageController;
|
use SilverStripe\CMS\Model\RedirectorPageController;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
@ -36,53 +36,65 @@ class RedirectorPageTest extends FunctionalTest
|
|||||||
Director::config()->set('alternate_base_url', 'http://www.mysite.com/');
|
Director::config()->set('alternate_base_url', 'http://www.mysite.com/');
|
||||||
|
|
||||||
// Ensure all pages are published
|
// Ensure all pages are published
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
foreach (Page::get() as $page) {
|
foreach (SiteTree::get() as $page) {
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGoodRedirectors()
|
public function testGoodRedirectors()
|
||||||
{
|
{
|
||||||
/* For good redirectors, the final destination URL will be returned */
|
// For good redirectors, the final destination URL will be returned
|
||||||
$this->assertEquals("http://www.google.com", $this->objFromFixture(RedirectorPage::class, 'goodexternal')->Link());
|
$this->assertEquals(
|
||||||
$this->assertEquals("/redirection-dest/", $this->objFromFixture(RedirectorPage::class, 'goodinternal')->redirectionLink());
|
"http://www.google.com",
|
||||||
$this->assertEquals("/redirection-dest/", $this->objFromFixture(RedirectorPage::class, 'goodinternal')->Link());
|
$this->objFromFixture(RedirectorPage::class, 'goodexternal')->Link()
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
"/redirection-dest",
|
||||||
|
$this->objFromFixture(RedirectorPage::class, 'goodinternal')->redirectionLink()
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
"/redirection-dest",
|
||||||
|
$this->objFromFixture(RedirectorPage::class, 'goodinternal')->Link()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEmptyRedirectors()
|
public function testEmptyRedirectors()
|
||||||
{
|
{
|
||||||
/* If a redirector page is misconfigured, then its link method will just return the usual URLSegment-generated value */
|
// If a redirector page is misconfigured, then its link method will just return the usual
|
||||||
|
// URLSegment-generated value
|
||||||
$page1 = $this->objFromFixture(RedirectorPage::class, 'badexternal');
|
$page1 = $this->objFromFixture(RedirectorPage::class, 'badexternal');
|
||||||
$this->assertEquals('/bad-external/', $page1->Link());
|
$this->assertEquals('/bad-external', $page1->Link());
|
||||||
|
|
||||||
/* An error message will be shown if you visit it */
|
// An error message will be shown if you visit it
|
||||||
$content = $this->get(Director::makeRelative($page1->Link()))->getBody();
|
$content = $this->get(Director::makeRelative($page1->Link()))->getBody();
|
||||||
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
||||||
|
|
||||||
/* This also applies for internal links */
|
// This also applies for internal links
|
||||||
$page2 = $this->objFromFixture(RedirectorPage::class, 'badinternal');
|
$page2 = $this->objFromFixture(RedirectorPage::class, 'badinternal');
|
||||||
$this->assertEquals('/bad-internal/', $page2->Link());
|
$this->assertEquals('/bad-internal', $page2->Link());
|
||||||
$content = $this->get(Director::makeRelative($page2->Link()))->getBody();
|
$content = $this->get(Director::makeRelative($page2->Link()))->getBody();
|
||||||
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReflexiveAndTransitiveInternalRedirectors()
|
public function testReflexiveAndTransitiveInternalRedirectors()
|
||||||
{
|
{
|
||||||
/* Reflexive redirectors are those that point to themselves. They should behave the same as an empty redirector */
|
// Reflexive redirectors are those that point to themselves.
|
||||||
|
// They should behave the same as an empty redirector
|
||||||
$page = $this->objFromFixture(RedirectorPage::class, 'reflexive');
|
$page = $this->objFromFixture(RedirectorPage::class, 'reflexive');
|
||||||
$this->assertEquals('/reflexive/', $page->Link());
|
$this->assertEquals('/reflexive', $page->Link());
|
||||||
$content = $this->get(Director::makeRelative($page->Link()))->getBody();
|
$content = $this->get(Director::makeRelative($page->Link()))->getBody();
|
||||||
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
$this->assertStringContainsString('message-setupWithoutRedirect', $content);
|
||||||
|
|
||||||
/* Transitive redirectors are those that point to another redirector page. They should send people to the URLSegment
|
// Transitive redirectors are those that point to another redirector page.
|
||||||
* of the destination page - the middle-stop, so to speak. That should redirect to the final destination */
|
// They should send people to the URLSegment of the destination page - the middle-stop, so to speak.
|
||||||
|
// That should redirect to the final destination
|
||||||
$page = $this->objFromFixture(RedirectorPage::class, 'transitive');
|
$page = $this->objFromFixture(RedirectorPage::class, 'transitive');
|
||||||
$this->assertEquals('/good-internal/', $page->Link());
|
$this->assertEquals('/good-internal', $page->Link());
|
||||||
|
|
||||||
$this->autoFollowRedirection = false;
|
$this->autoFollowRedirection = false;
|
||||||
$response = $this->get(Director::makeRelative($page->Link()));
|
$response = $this->get(Director::makeRelative($page->Link()));
|
||||||
$this->assertEquals(Director::absoluteURL('/redirection-dest/'), $response->getHeader("Location"));
|
$this->assertEquals(Director::absoluteURL('/redirection-dest'), $response->getHeader("Location"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testExternalURLGetsPrefixIfNotSet()
|
public function testExternalURLGetsPrefixIfNotSet()
|
||||||
@ -90,7 +102,11 @@ class RedirectorPageTest extends FunctionalTest
|
|||||||
$page = $this->objFromFixture(RedirectorPage::class, 'externalnoprefix');
|
$page = $this->objFromFixture(RedirectorPage::class, 'externalnoprefix');
|
||||||
$this->assertEquals($page->ExternalURL, 'http://google.com', 'onBeforeWrite has prefixed with http');
|
$this->assertEquals($page->ExternalURL, 'http://google.com', 'onBeforeWrite has prefixed with http');
|
||||||
$page->write();
|
$page->write();
|
||||||
$this->assertEquals($page->ExternalURL, 'http://google.com', 'onBeforeWrite will not double prefix if written again!');
|
$this->assertEquals(
|
||||||
|
$page->ExternalURL,
|
||||||
|
'http://google.com',
|
||||||
|
'onBeforeWrite will not double prefix if written again!'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAllowsProtocolRelative()
|
public function testAllowsProtocolRelative()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
dest:
|
dest:
|
||||||
Title: Redirection Dest
|
Title: Redirection Dest
|
||||||
URLSegment: redirection-dest
|
URLSegment: redirection-dest
|
||||||
@ -17,7 +17,7 @@ SilverStripe\CMS\Model\RedirectorPage:
|
|||||||
Title: Good Internal
|
Title: Good Internal
|
||||||
URLSegment: good-internal
|
URLSegment: good-internal
|
||||||
RedirectionType: Internal
|
RedirectionType: Internal
|
||||||
LinkTo: =>Page.dest
|
LinkTo: =>SilverStripe\CMS\Model\SiteTree.dest
|
||||||
badexternal:
|
badexternal:
|
||||||
Title: Bad External
|
Title: Bad External
|
||||||
RedirectionType: External
|
RedirectionType: External
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
use SilverStripe\Dev\FunctionalTest;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
@ -21,7 +20,6 @@ use SilverStripe\Versioned\Versioned;
|
|||||||
*/
|
*/
|
||||||
class SiteTreeActionsTest extends FunctionalTest
|
class SiteTreeActionsTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $fixture_file = 'SiteTreeActionsTest.yml';
|
protected static $fixture_file = 'SiteTreeActionsTest.yml';
|
||||||
|
|
||||||
public function testActionsReadonly()
|
public function testActionsReadonly()
|
||||||
@ -38,7 +36,7 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
Security::setCurrentUser($readonlyEditor);
|
Security::setCurrentUser($readonlyEditor);
|
||||||
|
|
||||||
// Reload latest version
|
// Reload latest version
|
||||||
$page = Page::get()->byID($page->ID);
|
$page = SiteTree::get()->byID($page->ID);
|
||||||
$actions = $page->getCMSActions();
|
$actions = $page->getCMSActions();
|
||||||
|
|
||||||
$this->assertNull($actions->dataFieldByName('action_save'));
|
$this->assertNull($actions->dataFieldByName('action_save'));
|
||||||
@ -84,14 +82,14 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
||||||
Security::setCurrentUser($author);
|
Security::setCurrentUser($author);
|
||||||
|
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->CanEditType = 'LoggedInUsers';
|
$page->CanEditType = 'LoggedInUsers';
|
||||||
$page->write();
|
$page->write();
|
||||||
$page->publishRecursive();
|
$page->publishRecursive();
|
||||||
|
|
||||||
// Reload latest version
|
// Reload latest version
|
||||||
$page = Page::get()->byID($page->ID);
|
$page = SiteTree::get()->byID($page->ID);
|
||||||
|
|
||||||
$actions = $page->getCMSActions();
|
$actions = $page->getCMSActions();
|
||||||
|
|
||||||
@ -108,7 +106,7 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
||||||
Security::setCurrentUser($author);
|
Security::setCurrentUser($author);
|
||||||
|
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->CanEditType = 'LoggedInUsers';
|
$page->CanEditType = 'LoggedInUsers';
|
||||||
$page->write();
|
$page->write();
|
||||||
$this->assertTrue($page->canPublish());
|
$this->assertTrue($page->canPublish());
|
||||||
@ -135,7 +133,7 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
$author = $this->objFromFixture(Member::class, 'cmseditor');
|
||||||
Security::setCurrentUser($author);
|
Security::setCurrentUser($author);
|
||||||
|
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->CanEditType = 'LoggedInUsers';
|
$page->CanEditType = 'LoggedInUsers';
|
||||||
$page->write();
|
$page->write();
|
||||||
$this->assertTrue($page->canPublish());
|
$this->assertTrue($page->canPublish());
|
||||||
@ -145,7 +143,7 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
$page->flushCache();
|
$page->flushCache();
|
||||||
|
|
||||||
// Reload latest version
|
// Reload latest version
|
||||||
$page = Page::get()->byID($page->ID);
|
$page = SiteTree::get()->byID($page->ID);
|
||||||
|
|
||||||
$actions = $page->getCMSActions();
|
$actions = $page->getCMSActions();
|
||||||
$this->assertNotNull($actions->dataFieldByName('action_save'));
|
$this->assertNotNull($actions->dataFieldByName('action_save'));
|
||||||
@ -158,15 +156,17 @@ class SiteTreeActionsTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testActionsViewingOldVersion()
|
public function testActionsViewingOldVersion()
|
||||||
{
|
{
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Content = 'test page first version';
|
$p->Content = 'test page first version';
|
||||||
$p->write();
|
$p->write();
|
||||||
$p->Content = 'new content';
|
$p->Content = 'new content';
|
||||||
$p->write();
|
$p->write();
|
||||||
|
|
||||||
// Looking at the old version, the ability to rollback to that version is available
|
// Looking at the old version, the ability to rollback to that version is available
|
||||||
$version = DB::query('SELECT "Version" FROM "SiteTree_Versions" WHERE "Content" = \'test page first version\'')->value();
|
$version = DB::query(
|
||||||
$old = Versioned::get_version('Page', $p->ID, $version);
|
'SELECT "Version" FROM "SiteTree_Versions" WHERE "Content" = \'test page first version\''
|
||||||
|
)->value();
|
||||||
|
$old = Versioned::get_version(SiteTree::class, $p->ID, $version);
|
||||||
$actions = $old->getCMSActions();
|
$actions = $old->getCMSActions();
|
||||||
$this->assertNull($actions->dataFieldByName('action_save'));
|
$this->assertNull($actions->dataFieldByName('action_save'));
|
||||||
$this->assertNull($actions->dataFieldByName('action_publish'));
|
$this->assertNull($actions->dataFieldByName('action_publish'));
|
||||||
|
@ -4,9 +4,9 @@ namespace SilverStripe\CMS\Tests\Model;
|
|||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\Security\Permission;
|
use SilverStripe\Security\Permission;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeActionsTest_Page extends Page implements TestOnly
|
class SiteTreeActionsTest_Page extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
public function canEdit($member = null)
|
public function canEdit($member = null)
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
|
|
||||||
protected static $required_extensions = [
|
protected static $required_extensions = [
|
||||||
SiteTree::class => [
|
SiteTree::class => [
|
||||||
SiteTreeBacklinksTest_DOD::class
|
SiteTreeBacklinksTest_DOD::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -34,10 +34,10 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
// testing here.
|
// testing here.
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$page3->Content = str_replace(
|
$page3->Content = str_replace(
|
||||||
'$page1.ID',
|
'$page1.ID',
|
||||||
$this->objFromFixture('Page', 'page1')->ID ?? '',
|
$this->objFromFixture(SiteTree::class, 'page1')->ID ?? '',
|
||||||
$page3->Content ?? ''
|
$page3->Content ?? ''
|
||||||
);
|
);
|
||||||
$page3->write();
|
$page3->write();
|
||||||
@ -46,18 +46,22 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
public function testSavingPageWithLinkAddsBacklink()
|
public function testSavingPageWithLinkAddsBacklink()
|
||||||
{
|
{
|
||||||
// load page 1
|
// load page 1
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
// assert backlink to page 2 doesn't exist
|
// assert backlink to page 2 doesn't exist
|
||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
$this->assertNotContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 doesn\'t exist');
|
$this->assertNotContains(
|
||||||
|
$page2->ID,
|
||||||
|
$page1->BackLinkTracking()->column('ID'),
|
||||||
|
'Assert backlink to page 2 doesn\'t exist'
|
||||||
|
);
|
||||||
|
|
||||||
// add hyperlink to page 1 on page 2
|
// add hyperlink to page 1 on page 2
|
||||||
$page2->Content .= '<p><a href="[sitetree_link,id='.$page1->ID.']">Testing page 1 link</a></p>';
|
$page2->Content .= '<p><a href="[sitetree_link,id=' . $page1->ID . ']">Testing page 1 link</a></p>';
|
||||||
$page2->write();
|
$page2->write();
|
||||||
|
|
||||||
// load page 1
|
// load page 1
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
// assert backlink to page 2 exists
|
// assert backlink to page 2 exists
|
||||||
$this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists');
|
$this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists');
|
||||||
@ -66,10 +70,10 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
public function testRemovingLinkFromPageRemovesBacklink()
|
public function testRemovingLinkFromPageRemovesBacklink()
|
||||||
{
|
{
|
||||||
// load page 1
|
// load page 1
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
// assert backlink to page 3 exits
|
// assert backlink to page 3 exits
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists');
|
$this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists');
|
||||||
|
|
||||||
// remove hyperlink to page 1
|
// remove hyperlink to page 1
|
||||||
@ -77,116 +81,156 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
$page3->write();
|
$page3->write();
|
||||||
|
|
||||||
// load page 1
|
// load page 1
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
// assert backlink to page 3 exists
|
// assert backlink to page 3 exists
|
||||||
$this->assertNotContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 doesn\'t exist');
|
$this->assertNotContains(
|
||||||
|
$page3->ID,
|
||||||
|
$page1->BackLinkTracking()->column('ID'),
|
||||||
|
'Assert backlink to page 3 doesn\'t exist'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testChangingUrlOnDraftSiteRewritesLink()
|
public function testChangingUrlOnDraftSiteRewritesLink()
|
||||||
{
|
{
|
||||||
// load page 1
|
// load page 1
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
|
|
||||||
// assert backlink to page 3 exists
|
// assert backlink to page 3 exists
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists');
|
$this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists');
|
||||||
|
|
||||||
// assert hyperlink to page 1's current url exists on page 3
|
// assert hyperlink to page 1's current url exists on page 3
|
||||||
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// change url of page 1
|
// change url of page 1
|
||||||
$page1->URLSegment = 'new-url-segment';
|
$page1->URLSegment = 'new-url-segment';
|
||||||
$page1->write();
|
$page1->write();
|
||||||
|
|
||||||
// load page 3
|
// load page 3
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
|
|
||||||
// assert hyperlink to page 1's new url exists
|
// assert hyperlink to page 1's new url exists
|
||||||
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'new-url-segment/', $links, 'Assert hyperlink to page 1\'s new url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'new-url-segment',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s new url exists on page 3'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testChangingUrlOnLiveSiteRewritesLink()
|
public function testChangingUrlOnLiveSiteRewritesLink()
|
||||||
{
|
{
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$this->assertTrue($page1->publishRecursive());
|
$this->assertTrue($page1->publishRecursive());
|
||||||
$this->assertTrue($page3->publishRecursive());
|
$this->assertTrue($page3->publishRecursive());
|
||||||
|
|
||||||
// load pages from live
|
// load pages from live
|
||||||
$page1live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page1->ID);
|
$page1live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page1->ID);
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
// assert backlink to page 3 exists
|
// assert backlink to page 3 exists
|
||||||
$this->assertContains($page3live->ID, $page1live->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists');
|
$this->assertContains(
|
||||||
|
$page3live->ID,
|
||||||
|
$page1live->BackLinkTracking()->column('ID'),
|
||||||
|
'Assert backlink to page 3 exists'
|
||||||
|
);
|
||||||
|
|
||||||
// assert hyperlink to page 1's current url exists on page 3
|
// assert hyperlink to page 1's current url exists on page 3
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// change url of page 1
|
// change url of page 1
|
||||||
$page1live->URLSegment = 'new-url-segment';
|
$page1live->URLSegment = 'new-url-segment';
|
||||||
$page1live->writeToStage('Live');
|
$page1live->writeToStage('Live');
|
||||||
|
|
||||||
// load page 3 from live
|
// load page 3 from live
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
// assert hyperlink to page 1's new url exists
|
// assert hyperlink to page 1's new url exists
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'new-url-segment/', $links, 'Assert hyperlink to page 1\'s new url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'new-url-segment',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s new url exists on page 3'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPublishingPageWithModifiedUrlRewritesLink()
|
public function testPublishingPageWithModifiedUrlRewritesLink()
|
||||||
{
|
{
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
|
|
||||||
$this->assertTrue($page1->publishRecursive());
|
$this->assertTrue($page1->publishRecursive());
|
||||||
$this->assertTrue($page3->publishRecursive());
|
$this->assertTrue($page3->publishRecursive());
|
||||||
|
|
||||||
// load page 3 from live
|
// load page 3 from live
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
// assert hyperlink to page 1's current url exists
|
// assert hyperlink to page 1's current url exists
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// rename url of page 1 on stage
|
// rename url of page 1 on stage
|
||||||
$page1->URLSegment = 'new-url-segment';
|
$page1->URLSegment = 'new-url-segment';
|
||||||
$page1->write();
|
$page1->write();
|
||||||
|
|
||||||
// assert hyperlink to page 1's current publish url exists
|
// assert hyperlink to page 1's current publish url exists
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current published url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// publish page 1
|
// publish page 1
|
||||||
$this->assertTrue($page1->publishRecursive());
|
$this->assertTrue($page1->publishRecursive());
|
||||||
|
|
||||||
// assert hyperlink to page 1's new published url exists
|
// assert hyperlink to page 1's new published url exists
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'new-url-segment/', $links, 'Assert hyperlink to page 1\'s new published url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'new-url-segment',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s new published url exists on page 3'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPublishingPageWithModifiedLinksRewritesLinks()
|
public function testPublishingPageWithModifiedLinksRewritesLinks()
|
||||||
{
|
{
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$this->assertTrue($page1->publishRecursive());
|
$this->assertTrue($page1->publishRecursive());
|
||||||
$this->assertTrue($page3->publishRecursive());
|
$this->assertTrue($page3->publishRecursive());
|
||||||
|
|
||||||
// assert hyperlink to page 1's current url exists
|
// assert hyperlink to page 1's current url exists
|
||||||
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current published url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// change page 1 url on draft
|
// change page 1 url on draft
|
||||||
$page1->URLSegment = 'new-url-segment';
|
$page1->URLSegment = 'new-url-segment';
|
||||||
@ -195,42 +239,58 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
$page1->write();
|
$page1->write();
|
||||||
|
|
||||||
// assert page 3 on draft contains new page 1 url
|
// assert page 3 on draft contains new page 1 url
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture(SiteTree::class, 'page3');
|
||||||
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'new-url-segment/', $links, 'Assert hyperlink to page 1\'s current draft url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'new-url-segment',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current draft url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// publish page 3
|
// publish page 3
|
||||||
$this->assertTrue($page3->publishRecursive());
|
$this->assertTrue($page3->publishRecursive());
|
||||||
|
|
||||||
// assert page 3 on published site contains old page 1 url
|
// assert page 3 on published site contains old page 1 url
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'page1',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current published url exists on page 3'
|
||||||
|
);
|
||||||
|
|
||||||
// publish page 1
|
// publish page 1
|
||||||
$this->assertTrue($page1->publishRecursive());
|
$this->assertTrue($page1->publishRecursive());
|
||||||
|
|
||||||
// assert page 3 on published site contains new page 1 url
|
// assert page 3 on published site contains new page 1 url
|
||||||
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
$page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
$links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate());
|
||||||
$this->assertContains(Director::baseURL().'new-url-segment/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
$this->assertContains(
|
||||||
|
Director::baseURL() . 'new-url-segment',
|
||||||
|
$links,
|
||||||
|
'Assert hyperlink to page 1\'s current published url exists on page 3'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLinkTrackingOnExtraContentFields()
|
public function testLinkTrackingOnExtraContentFields()
|
||||||
{
|
{
|
||||||
/** @var Page $page1 */
|
/** @var SiteTree $page1 */
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
/** @var Page $page2 */
|
/** @var SiteTree $page2 */
|
||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
$page1->publishRecursive();
|
$page1->publishRecursive();
|
||||||
$page2->publishRecursive();
|
$page2->publishRecursive();
|
||||||
|
|
||||||
// assert backlink to page 2 doesn't exist
|
// assert backlink to page 2 doesn't exist
|
||||||
$this->assertNotContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 doesn\'t exist');
|
$this->assertNotContains(
|
||||||
|
$page2->ID,
|
||||||
|
$page1->BackLinkTracking()->column('ID'),
|
||||||
|
'Assert backlink to page 2 doesn\'t exist'
|
||||||
|
);
|
||||||
|
|
||||||
// add hyperlink to page 1 on page 2
|
// add hyperlink to page 1 on page 2
|
||||||
$page2->ExtraContent .= '<p><a href="[sitetree_link,id='.$page1->ID.']">Testing page 1 link</a></p>';
|
$page2->ExtraContent .= '<p><a href="[sitetree_link,id=' . $page1->ID . ']">Testing page 1 link</a></p>';
|
||||||
$page2->write();
|
$page2->write();
|
||||||
$page2->publishRecursive();
|
$page2->publishRecursive();
|
||||||
|
|
||||||
@ -238,23 +298,32 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
$this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists');
|
$this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists');
|
||||||
|
|
||||||
// update page1 url
|
// update page1 url
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture(SiteTree::class, 'page1');
|
||||||
$page1->URLSegment = "page1-new-url";
|
$page1->URLSegment = "page1-new-url";
|
||||||
$page1->write();
|
$page1->write();
|
||||||
|
|
||||||
// confirm that draft link on page2 has been rewritten
|
// confirm that draft link on page2 has been rewritten
|
||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
$this->assertEquals('<p><a href="'.Director::baseURL().'page1-new-url/">Testing page 1 link</a></p>', $page2->obj('ExtraContent')->forTemplate());
|
$this->assertEquals(
|
||||||
|
'<p><a href="' . Director::baseURL() . 'page1-new-url">Testing page 1 link</a></p>',
|
||||||
|
$page2->obj('ExtraContent')->forTemplate()
|
||||||
|
);
|
||||||
|
|
||||||
// confirm that published link hasn't
|
// confirm that published link hasn't
|
||||||
$page2Live = Versioned::get_one_by_stage("Page", "Live", "\"SiteTree\".\"ID\" = $page2->ID");
|
$page2Live = Versioned::get_one_by_stage(SiteTree::class, "Live", "\"SiteTree\".\"ID\" = $page2->ID");
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$this->assertEquals('<p><a href="'.Director::baseURL().'page1/">Testing page 1 link</a></p>', $page2Live->obj('ExtraContent')->forTemplate());
|
$this->assertEquals(
|
||||||
|
'<p><a href="' . Director::baseURL() . 'page1">Testing page 1 link</a></p>',
|
||||||
|
$page2Live->obj('ExtraContent')->forTemplate()
|
||||||
|
);
|
||||||
|
|
||||||
// publish page1 and confirm that the link on the published page2 has now been updated
|
// publish page1 and confirm that the link on the published page2 has now been updated
|
||||||
$page1->publishRecursive();
|
$page1->publishRecursive();
|
||||||
$page2Live = Versioned::get_one_by_stage("Page", "Live", "\"SiteTree\".\"ID\" = $page2->ID");
|
$page2Live = Versioned::get_one_by_stage(SiteTree::class, "Live", "\"SiteTree\".\"ID\" = $page2->ID");
|
||||||
$this->assertEquals('<p><a href="'.Director::baseURL().'page1-new-url/">Testing page 1 link</a></p>', $page2Live->obj('ExtraContent')->forTemplate());
|
$this->assertEquals(
|
||||||
|
'<p><a href="' . Director::baseURL() . 'page1-new-url">Testing page 1 link</a></p>',
|
||||||
|
$page2Live->obj('ExtraContent')->forTemplate()
|
||||||
|
);
|
||||||
|
|
||||||
// Edit draft again
|
// Edit draft again
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
@ -262,12 +331,16 @@ class SiteTreeBacklinksTest extends SapphireTest
|
|||||||
$page2->write();
|
$page2->write();
|
||||||
|
|
||||||
// assert backlink to page 2 no longer exists
|
// assert backlink to page 2 no longer exists
|
||||||
$this->assertNotContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 has been removed');
|
$this->assertNotContains(
|
||||||
|
$page2->ID,
|
||||||
|
$page1->BackLinkTracking()->column('ID'),
|
||||||
|
'Assert backlink to page 2 has been removed'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLinkTrackingWithUntitledObjectsDisplaysAReadableIdentifier()
|
public function testLinkTrackingWithUntitledObjectsDisplaysAReadableIdentifier()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture('Page', 'page2');
|
$page = $this->objFromFixture(SiteTree::class, 'page2');
|
||||||
|
|
||||||
$referencingObject = new SiteTreeBacklinksTestContentObject();
|
$referencingObject = new SiteTreeBacklinksTestContentObject();
|
||||||
$referencingObject->Content = '<p><a href="[sitetree_link,id='
|
$referencingObject->Content = '<p><a href="[sitetree_link,id='
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
page1:
|
page1:
|
||||||
Title: page1
|
Title: page1
|
||||||
URLSegment: page1
|
URLSegment: page1
|
||||||
@ -11,6 +11,6 @@ Page:
|
|||||||
Title: page3
|
Title: page3
|
||||||
URLSegment: page3
|
URLSegment: page3
|
||||||
Content: '<p><a href="[sitetree_link,id=$page1.ID]">Testing page 1 link</a></p>'
|
Content: '<p><a href="[sitetree_link,id=$page1.ID]">Testing page 1 link</a></p>'
|
||||||
LinkTracking: =>Page.page1
|
LinkTracking: =>SilverStripe\CMS\Model\SiteTree.page1
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use Silverstripe\Assets\Dev\TestAssetStore;
|
use Silverstripe\Assets\Dev\TestAssetStore;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
@ -42,15 +41,15 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenLinksBetweenPages()
|
public function testBrokenLinksBetweenPages()
|
||||||
{
|
{
|
||||||
/** @var Page $obj */
|
/** @var SiteTree $obj */
|
||||||
$obj = $this->objFromFixture('Page', 'content');
|
$obj = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
|
|
||||||
$obj->Content = '<a href="[sitetree_link,id=3423423]">this is a broken link</a>';
|
$obj->Content = '<a href="[sitetree_link,id=3423423]">this is a broken link</a>';
|
||||||
$obj->syncLinkTracking();
|
$obj->syncLinkTracking();
|
||||||
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken link');
|
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken link');
|
||||||
|
|
||||||
$obj->Content = '<a href="[sitetree_link,id=' . $this->idFromFixture(
|
$obj->Content = '<a href="[sitetree_link,id=' . $this->idFromFixture(
|
||||||
'Page',
|
SiteTree::class,
|
||||||
'about'
|
'about'
|
||||||
) . ']">this is not a broken link</a>';
|
) . ']">this is not a broken link</a>';
|
||||||
$obj->syncLinkTracking();
|
$obj->syncLinkTracking();
|
||||||
@ -62,8 +61,8 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function testBrokenLinksNonPage()
|
public function testBrokenLinksNonPage()
|
||||||
{
|
{
|
||||||
/** @var Page $aboutPage */
|
/** @var SiteTree $aboutPage */
|
||||||
$aboutPage = $this->objFromFixture('Page', 'about');
|
$aboutPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
|
|
||||||
/** @var NotPageObject $obj */
|
/** @var NotPageObject $obj */
|
||||||
$obj = $this->objFromFixture(NotPageObject::class, 'object1');
|
$obj = $this->objFromFixture(NotPageObject::class, 'object1');
|
||||||
@ -94,7 +93,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
// About-page backlinks contains this object
|
// About-page backlinks contains this object
|
||||||
$this->assertListEquals(
|
$this->assertListEquals(
|
||||||
[
|
[
|
||||||
['ID' => $obj->ID]
|
['ID' => $obj->ID],
|
||||||
],
|
],
|
||||||
$aboutPage->BackLinkTracking()
|
$aboutPage->BackLinkTracking()
|
||||||
);
|
);
|
||||||
@ -102,9 +101,9 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenAnchorBetweenPages()
|
public function testBrokenAnchorBetweenPages()
|
||||||
{
|
{
|
||||||
/** @var Page $obj */
|
/** @var SiteTree $obj */
|
||||||
$obj = $this->objFromFixture('Page', 'content');
|
$obj = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$target = $this->objFromFixture('Page', 'about');
|
$target = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
|
|
||||||
$obj->Content = "<a href=\"[sitetree_link,id={$target->ID}]#no-anchor-here\">this is a broken link</a>";
|
$obj->Content = "<a href=\"[sitetree_link,id={$target->ID}]#no-anchor-here\">this is a broken link</a>";
|
||||||
$obj->syncLinkTracking();
|
$obj->syncLinkTracking();
|
||||||
@ -117,7 +116,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenVirtualPages()
|
public function testBrokenVirtualPages()
|
||||||
{
|
{
|
||||||
$obj = $this->objFromFixture('Page', 'content');
|
$obj = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$vp = new VirtualPage();
|
$vp = new VirtualPage();
|
||||||
|
|
||||||
$vp->CopyContentFromID = $obj->ID;
|
$vp->CopyContentFromID = $obj->ID;
|
||||||
@ -131,7 +130,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenInternalRedirectorPages()
|
public function testBrokenInternalRedirectorPages()
|
||||||
{
|
{
|
||||||
$obj = $this->objFromFixture('Page', 'content');
|
$obj = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$rp = new RedirectorPage();
|
$rp = new RedirectorPage();
|
||||||
|
|
||||||
$rp->RedirectionType = 'Internal';
|
$rp->RedirectionType = 'Internal';
|
||||||
@ -148,10 +147,10 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
public function testDeletingMarksBackLinkedPagesAsBroken()
|
public function testDeletingMarksBackLinkedPagesAsBroken()
|
||||||
{
|
{
|
||||||
// Set up two published pages with a link from content -> about
|
// Set up two published pages with a link from content -> about
|
||||||
$linkDest = $this->objFromFixture('Page', 'about');
|
$linkDest = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
|
|
||||||
/** @var Page $linkSrc */
|
/** @var SiteTree $linkSrc */
|
||||||
$linkSrc = $this->objFromFixture('Page', 'content');
|
$linkSrc = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
||||||
$linkSrc->write();
|
$linkSrc->write();
|
||||||
|
|
||||||
@ -163,7 +162,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
// Confirm draft has broken link
|
// Confirm draft has broken link
|
||||||
$linkSrc->flushCache();
|
$linkSrc->flushCache();
|
||||||
$linkSrc = $this->objFromFixture('Page', 'content');
|
$linkSrc = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
|
|
||||||
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
||||||
}
|
}
|
||||||
@ -173,13 +172,13 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
// Set up two draft pages with a link from content -> about
|
// Set up two draft pages with a link from content -> about
|
||||||
/** @var Page $linkDest */
|
/** @var SiteTree $linkDest */
|
||||||
$linkDest = $this->objFromFixture('Page', 'about');
|
$linkDest = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
// Ensure that it's not on the published site
|
// Ensure that it's not on the published site
|
||||||
$linkDest->doUnpublish();
|
$linkDest->doUnpublish();
|
||||||
|
|
||||||
/** @var Page $linkSrc */
|
/** @var SiteTree $linkSrc */
|
||||||
$linkSrc = $this->objFromFixture('Page', 'content');
|
$linkSrc = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
||||||
$linkSrc->write();
|
$linkSrc->write();
|
||||||
|
|
||||||
@ -191,20 +190,20 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
// Live doesn't have separate broken link tracking
|
// Live doesn't have separate broken link tracking
|
||||||
$this->assertEquals(0, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
$this->assertEquals(0, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
||||||
WHERE \"ID\" = $linkSrc->ID")->value());
|
WHERE \"ID\" = $linkSrc->ID")->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestoreFixesBrokenLinks()
|
public function testRestoreFixesBrokenLinks()
|
||||||
{
|
{
|
||||||
// Create page and virtual page
|
// Create page and virtual page
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Title = "source";
|
$p->Title = "source";
|
||||||
$p->write();
|
$p->write();
|
||||||
$pageID = $p->ID;
|
$pageID = $p->ID;
|
||||||
$this->assertTrue($p->publishRecursive());
|
$this->assertTrue($p->publishRecursive());
|
||||||
|
|
||||||
// Content links are one kind of link to pages
|
// Content links are one kind of link to pages
|
||||||
$p2 = new Page();
|
$p2 = new SiteTree();
|
||||||
$p2->Title = "regular link";
|
$p2->Title = "regular link";
|
||||||
$p2->Content = "<a href=\"[sitetree_link,id=$p->ID]\">test</a>";
|
$p2->Content = "<a href=\"[sitetree_link,id=$p->ID]\">test</a>";
|
||||||
$p2->write();
|
$p2->write();
|
||||||
@ -264,14 +263,14 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
public function testRevertToLiveFixesBrokenLinks()
|
public function testRevertToLiveFixesBrokenLinks()
|
||||||
{
|
{
|
||||||
// Create page and virutal page
|
// Create page and virutal page
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->Title = "source";
|
$page->Title = "source";
|
||||||
$page->write();
|
$page->write();
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$this->assertTrue($page->publishRecursive());
|
$this->assertTrue($page->publishRecursive());
|
||||||
|
|
||||||
// Content links are one kind of link to pages
|
// Content links are one kind of link to pages
|
||||||
$page2 = new Page();
|
$page2 = new SiteTree();
|
||||||
$page2->Title = "regular link";
|
$page2->Title = "regular link";
|
||||||
$page2->Content = "<a href=\"[sitetree_link,id={$pageID}]\">test</a>";
|
$page2->Content = "<a href=\"[sitetree_link,id={$pageID}]\">test</a>";
|
||||||
$page2->write();
|
$page2->write();
|
||||||
@ -302,7 +301,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
$this->assertEquals(1, $redirectorPage->HasBrokenLink);
|
$this->assertEquals(1, $redirectorPage->HasBrokenLink);
|
||||||
|
|
||||||
// Call doRevertToLive and confirm that broken links are restored
|
// Call doRevertToLive and confirm that broken links are restored
|
||||||
/** @var Page $pageLive */
|
/** @var SiteTree $pageLive */
|
||||||
$pageLive = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $pageID);
|
$pageLive = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $pageID);
|
||||||
$pageLive->doRevertToLive();
|
$pageLive->doRevertToLive();
|
||||||
|
|
||||||
@ -316,15 +315,17 @@ class SiteTreeBrokenLinksTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenAnchorLinksInAPage()
|
public function testBrokenAnchorLinksInAPage()
|
||||||
{
|
{
|
||||||
/** @var Page $obj */
|
/** @var SiteTree $obj */
|
||||||
$obj = $this->objFromFixture('Page', 'content');
|
$obj = $this->objFromFixture(SiteTree::class, 'content');
|
||||||
$origContent = $obj->Content;
|
$origContent = $obj->Content;
|
||||||
|
|
||||||
$obj->Content = $origContent . '<a href="#no-anchor-here">this links to a non-existent in-page anchor or skiplink</a>';
|
$obj->Content = $origContent . '<a href="#no-anchor-here">this links to a non-existent in-page anchor or ' .
|
||||||
|
'skiplink</a>';
|
||||||
$obj->syncLinkTracking();
|
$obj->syncLinkTracking();
|
||||||
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken anchor/skiplink');
|
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken anchor/skiplink');
|
||||||
|
|
||||||
$obj->Content = $origContent . '<a href="#yes-anchor-here">this links to an existent in-page anchor/skiplink</a>';
|
$obj->Content = $origContent . '<a href="#yes-anchor-here">this links to an existent in-page ' .
|
||||||
|
'anchor/skiplink</a>';
|
||||||
$obj->syncLinkTracking();
|
$obj->syncLinkTracking();
|
||||||
$this->assertFalse($obj->HasBrokenLink, 'Page doesn\'t have a broken anchor or skiplink');
|
$this->assertFalse($obj->HasBrokenLink, 'Page doesn\'t have a broken anchor or skiplink');
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
content:
|
content:
|
||||||
Title: ContentPage
|
Title: ContentPage
|
||||||
Content: 'This is some partially happy content. It has one missing a skiplink, but does have another <a name="yes-anchor-here">skiplink here</a>.'
|
Content: 'This is some partially happy content. It has one missing a skiplink, but does have another <a name="yes-anchor-here">skiplink here</a>.'
|
||||||
@ -13,7 +13,7 @@ Page:
|
|||||||
workingInternalRedirector:
|
workingInternalRedirector:
|
||||||
RedirectionType: Internal
|
RedirectionType: Internal
|
||||||
Title: RedirectorPageToBrokenInteralPage
|
Title: RedirectorPageToBrokenInteralPage
|
||||||
LinkTo: =>Page.content
|
LinkTo: =>SilverStripe\CMS\Model\SiteTree.content
|
||||||
SilverStripe\CMS\Tests\Model\SiteTreeBrokenLinksTest\NotPageObject:
|
SilverStripe\CMS\Tests\Model\SiteTreeBrokenLinksTest\NotPageObject:
|
||||||
object1:
|
object1:
|
||||||
Content: 'Everything will be ok'
|
Content: 'Everything will be ok'
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\Assets\Dev\TestAssetStore;
|
use SilverStripe\Assets\Dev\TestAssetStore;
|
||||||
use SilverStripe\Assets\File;
|
use SilverStripe\Assets\File;
|
||||||
use SilverStripe\Assets\Filesystem;
|
use SilverStripe\Assets\Filesystem;
|
||||||
@ -31,8 +30,8 @@ class SiteTreeHTMLEditorFieldTest extends FunctionalTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure all pages are published
|
// Ensure all pages are published
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
foreach (Page::get() as $page) {
|
foreach (SiteTree::get() as $page) {
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +54,11 @@ class SiteTreeHTMLEditorFieldTest extends FunctionalTest
|
|||||||
$editor->setValue("<a href=\"[sitetree_link,id=$aboutID]\">Example Link</a>");
|
$editor->setValue("<a href=\"[sitetree_link,id=$aboutID]\">Example Link</a>");
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
$sitetree->write();
|
$sitetree->write();
|
||||||
$this->assertEquals([$aboutID => $aboutID], $sitetree->LinkTracking()->getIdList(), 'Basic link tracking works.');
|
$this->assertEquals(
|
||||||
|
[$aboutID => $aboutID],
|
||||||
|
$sitetree->LinkTracking()->getIdList(),
|
||||||
|
'Basic link tracking works.'
|
||||||
|
);
|
||||||
|
|
||||||
$editor->setValue(
|
$editor->setValue(
|
||||||
"<a href=\"[sitetree_link,id=$aboutID]\"></a><a href=\"[sitetree_link,id=$contactID]\"></a>"
|
"<a href=\"[sitetree_link,id=$aboutID]\"></a><a href=\"[sitetree_link,id=$contactID]\"></a>"
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\CMS\Model\SiteTreeLinkTracking_Parser;
|
use SilverStripe\CMS\Model\SiteTreeLinkTracking_Parser;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
@ -32,7 +31,7 @@ class SiteTreeLinkTrackingTest extends SapphireTest
|
|||||||
|
|
||||||
public function testParser()
|
public function testParser()
|
||||||
{
|
{
|
||||||
SiteTree::add_extension(Page::class, SiteTreeLinkTracking_Extension::class);
|
SiteTree::add_extension(SiteTree::class, SiteTreeLinkTracking_Extension::class);
|
||||||
|
|
||||||
// Shortcodes
|
// Shortcodes
|
||||||
$this->assertTrue($this->isBroken('<a href="[sitetree_link,id=123]">link</a>'));
|
$this->assertTrue($this->isBroken('<a href="[sitetree_link,id=123]">link</a>'));
|
||||||
@ -55,8 +54,7 @@ class SiteTreeLinkTrackingTest extends SapphireTest
|
|||||||
$this->assertFalse($this->isBroken('<a id="anchor">anchor</a>'));
|
$this->assertFalse($this->isBroken('<a id="anchor">anchor</a>'));
|
||||||
$this->assertTrue($this->isBroken('<a href="##anchor">anchor</a>'));
|
$this->assertTrue($this->isBroken('<a href="##anchor">anchor</a>'));
|
||||||
|
|
||||||
|
$page = new SiteTree();
|
||||||
$page = new Page();
|
|
||||||
$page->Content = '<a name="yes-name-anchor">name</a><a id="yes-id-anchor">id</a>';
|
$page->Content = '<a name="yes-name-anchor">name</a><a id="yes-id-anchor">id</a>';
|
||||||
$page->write();
|
$page->write();
|
||||||
|
|
||||||
@ -72,7 +70,7 @@ class SiteTreeLinkTrackingTest extends SapphireTest
|
|||||||
|
|
||||||
protected function highlight($content)
|
protected function highlight($content)
|
||||||
{
|
{
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->Content = $content;
|
$page->Content = $content;
|
||||||
$page->write();
|
$page->write();
|
||||||
return $page->Content;
|
return $page->Content;
|
||||||
@ -87,7 +85,7 @@ class SiteTreeLinkTrackingTest extends SapphireTest
|
|||||||
$content = $this->highlight('<a href="[sitetree_link,id=123]">link</a>');
|
$content = $this->highlight('<a href="[sitetree_link,id=123]">link</a>');
|
||||||
$this->assertEquals(substr_count($content ?? '', 'ss-broken'), 1, 'ss-broken class is added to the broken link.');
|
$this->assertEquals(substr_count($content ?? '', 'ss-broken'), 1, 'ss-broken class is added to the broken link.');
|
||||||
|
|
||||||
$otherPage = new Page();
|
$otherPage = new SiteTree();
|
||||||
$otherPage->Content = '';
|
$otherPage->Content = '';
|
||||||
$otherPage->write();
|
$otherPage->write();
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Control\HTTPResponse_Exception;
|
use SilverStripe\Control\HTTPResponse_Exception;
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
use SilverStripe\Dev\FunctionalTest;
|
||||||
@ -33,8 +32,8 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$this->autoFollowRedirection = false;
|
$this->autoFollowRedirection = false;
|
||||||
|
|
||||||
// Ensure all pages are published
|
// Ensure all pages are published
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
foreach (Page::get() as $page) {
|
foreach (SiteTree::get() as $page) {
|
||||||
if ($page->URLSegment !== 'draft-only') {
|
if ($page->URLSegment !== 'draft-only') {
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
}
|
}
|
||||||
@ -46,8 +45,8 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
$this->autoFollowRedirection = false;
|
$this->autoFollowRedirection = false;
|
||||||
|
|
||||||
/** @var Page $draftOnlyPage */
|
/** @var SiteTree $draftOnlyPage */
|
||||||
$draftOnlyPage = $this->objFromFixture(Page::class, 'draftOnlyPage');
|
$draftOnlyPage = $this->objFromFixture(SiteTree::class, 'draftOnlyPage');
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
|
|
||||||
$response = $this->get($draftOnlyPage->URLSegment . '?stage=Live');
|
$response = $this->get($draftOnlyPage->URLSegment . '?stage=Live');
|
||||||
@ -85,7 +84,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
// Set up fixture - a published page deleted from draft
|
// Set up fixture - a published page deleted from draft
|
||||||
$this->logInWithPermission("ADMIN");
|
$this->logInWithPermission("ADMIN");
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditOnlySubadminGroup');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditOnlySubadminGroup');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$this->assertTrue($page->publishRecursive());
|
$this->assertTrue($page->publishRecursive());
|
||||||
$page->delete();
|
$page->delete();
|
||||||
@ -112,7 +111,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
// Set up fixture - an unpublished page
|
// Set up fixture - an unpublished page
|
||||||
$this->logInWithPermission("ADMIN");
|
$this->logInWithPermission("ADMIN");
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditOnlySubadminGroup');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditOnlySubadminGroup');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$page->doUnpublish();
|
$page->doUnpublish();
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
// Find a page that exists and delete it from both stage and published
|
// Find a page that exists and delete it from both stage and published
|
||||||
$this->logInWithPermission("ADMIN");
|
$this->logInWithPermission("ADMIN");
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditOnlySubadminGroup');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditOnlySubadminGroup');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$page->doUnpublish();
|
$page->doUnpublish();
|
||||||
$page->delete();
|
$page->delete();
|
||||||
@ -153,8 +152,8 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
public function testCanViewStage()
|
public function testCanViewStage()
|
||||||
{
|
{
|
||||||
// Get page & make sure it exists on Live
|
// Get page & make sure it exists on Live
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
$page = $this->objFromFixture(Page::class, 'standardpage');
|
$page = $this->objFromFixture(SiteTree::class, 'standardpage');
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
|
|
||||||
// Then make sure there's a new version on Stage
|
// Then make sure there's a new version on Stage
|
||||||
@ -173,7 +172,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testAccessTabOnlyDisplaysWithGrantAccessPermissions()
|
public function testAccessTabOnlyDisplaysWithGrantAccessPermissions()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'standardpage');
|
$page = $this->objFromFixture(SiteTree::class, 'standardpage');
|
||||||
|
|
||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
Security::setCurrentUser($subadminuser);
|
Security::setCurrentUser($subadminuser);
|
||||||
@ -204,7 +203,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testRestrictedViewLoggedInUsers()
|
public function testRestrictedViewLoggedInUsers()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedViewLoggedInUsers');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedViewLoggedInUsers');
|
||||||
|
|
||||||
// unauthenticated users
|
// unauthenticated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -223,21 +222,23 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$websiteuser = $this->objFromFixture(Member::class, 'websiteuser');
|
$websiteuser = $this->objFromFixture(Member::class, 'websiteuser');
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$page->canView($websiteuser),
|
$page->canView($websiteuser),
|
||||||
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont have access to the CMS'
|
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont ' .
|
||||||
|
'have access to the CMS'
|
||||||
);
|
);
|
||||||
$this->logInAs($websiteuser);
|
$this->logInAs($websiteuser);
|
||||||
$response = $this->get($page->RelativeLink());
|
$response = $this->get($page->RelativeLink());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$response->getStatusCode(),
|
$response->getStatusCode(),
|
||||||
200,
|
200,
|
||||||
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont have access to the CMS'
|
'Authenticated members can view a page marked as "Viewable for any logged in users" even if they dont ' .
|
||||||
|
'have access to the CMS'
|
||||||
);
|
);
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestrictedViewOnlyTheseUsers()
|
public function testRestrictedViewOnlyTheseUsers()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedViewOnlyWebsiteUsers');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedViewOnlyWebsiteUsers');
|
||||||
|
|
||||||
// unauthenticcated users
|
// unauthenticcated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -256,14 +257,16 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
$page->canView($subadminuser),
|
$page->canView($subadminuser),
|
||||||
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
|
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed ' .
|
||||||
|
'groups'
|
||||||
);
|
);
|
||||||
$this->LogInAs($subadminuser);
|
$this->LogInAs($subadminuser);
|
||||||
$response = $this->get($page->RelativeLink());
|
$response = $this->get($page->RelativeLink());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$response->getStatusCode(),
|
$response->getStatusCode(),
|
||||||
403,
|
403,
|
||||||
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed groups'
|
'Authenticated members cant view a page marked as "Viewable by these groups" if theyre not in the listed ' .
|
||||||
|
'groups'
|
||||||
);
|
);
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
|
|
||||||
@ -285,7 +288,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testRestrictedEditLoggedInUsers()
|
public function testRestrictedEditLoggedInUsers()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditLoggedInUsers');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditLoggedInUsers');
|
||||||
|
|
||||||
// unauthenticcated users
|
// unauthenticcated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -298,20 +301,22 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
Security::setCurrentUser($websiteuser);
|
Security::setCurrentUser($websiteuser);
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
$page->canEdit($websiteuser),
|
$page->canEdit($websiteuser),
|
||||||
'Authenticated members cant edit a page marked as "Editable by logged in users" if they dont have cms permissions'
|
'Authenticated members cant edit a page marked as "Editable by logged in users" if they dont have cms ' .
|
||||||
|
'permissions'
|
||||||
);
|
);
|
||||||
|
|
||||||
// subadmin users
|
// subadmin users
|
||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$page->canEdit($subadminuser),
|
$page->canEdit($subadminuser),
|
||||||
'Authenticated members can edit a page marked as "Editable by logged in users" if they have cms permissions and belong to any of these groups'
|
'Authenticated members can edit a page marked as "Editable by logged in users" if they have cms ' .
|
||||||
|
'permissions and belong to any of these groups'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestrictedEditOnlySubadminGroup()
|
public function testRestrictedEditOnlySubadminGroup()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditOnlySubadminGroup');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditOnlySubadminGroup');
|
||||||
|
|
||||||
// unauthenticated users
|
// unauthenticated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -330,14 +335,15 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$websiteuser = $this->objFromFixture(Member::class, 'websiteuser');
|
$websiteuser = $this->objFromFixture(Member::class, 'websiteuser');
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
$page->canEdit($websiteuser),
|
$page->canEdit($websiteuser),
|
||||||
'Authenticated members cant edit a page marked as "Editable by these groups" if theyre not in the listed groups'
|
'Authenticated members cant edit a page marked as "Editable by these groups" if theyre not in the listed ' .
|
||||||
|
'groups'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestrictedViewInheritance()
|
public function testRestrictedViewInheritance()
|
||||||
{
|
{
|
||||||
$parentPage = $this->objFromFixture(Page::class, 'parent_restrictedViewOnlySubadminGroup');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'parent_restrictedViewOnlySubadminGroup');
|
||||||
$childPage = $this->objFromFixture(Page::class, 'child_restrictedViewOnlySubadminGroup');
|
$childPage = $this->objFromFixture(SiteTree::class, 'child_restrictedViewOnlySubadminGroup');
|
||||||
|
|
||||||
// unauthenticated users
|
// unauthenticated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -356,22 +362,24 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$childPage->canView($subadminuser),
|
$childPage->canView($subadminuser),
|
||||||
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups by inherited permission'
|
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed ' .
|
||||||
|
'groups by inherited permission'
|
||||||
);
|
);
|
||||||
$this->logInAs($subadminuser);
|
$this->logInAs($subadminuser);
|
||||||
$response = $this->get($childPage->RelativeLink());
|
$response = $this->get($childPage->RelativeLink());
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$response->getStatusCode(),
|
$response->getStatusCode(),
|
||||||
200,
|
200,
|
||||||
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed groups by inherited permission'
|
'Authenticated members can view a page marked as "Viewable by these groups" if theyre in the listed ' .
|
||||||
|
'groups by inherited permission'
|
||||||
);
|
);
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRestrictedEditInheritance()
|
public function testRestrictedEditInheritance()
|
||||||
{
|
{
|
||||||
$parentPage = $this->objFromFixture(Page::class, 'parent_restrictedEditOnlySubadminGroup');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'parent_restrictedEditOnlySubadminGroup');
|
||||||
$childPage = $this->objFromFixture(Page::class, 'child_restrictedEditOnlySubadminGroup');
|
$childPage = $this->objFromFixture(SiteTree::class, 'child_restrictedEditOnlySubadminGroup');
|
||||||
|
|
||||||
// unauthenticated users
|
// unauthenticated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -383,14 +391,15 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$childPage->canEdit($subadminuser),
|
$childPage->canEdit($subadminuser),
|
||||||
'Authenticated members can edit a page marked as "Editable by these groups" if theyre in the listed groups by inherited permission'
|
'Authenticated members can edit a page marked as "Editable by these groups" if theyre in the listed ' .
|
||||||
|
'groups by inherited permission'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeleteRestrictedChild()
|
public function testDeleteRestrictedChild()
|
||||||
{
|
{
|
||||||
$parentPage = $this->objFromFixture(Page::class, 'deleteTestParentPage');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'deleteTestParentPage');
|
||||||
$childPage = $this->objFromFixture(Page::class, 'deleteTestChildPage');
|
$childPage = $this->objFromFixture(SiteTree::class, 'deleteTestChildPage');
|
||||||
|
|
||||||
// unauthenticated users
|
// unauthenticated users
|
||||||
$this->assertFalse(
|
$this->assertFalse(
|
||||||
@ -405,7 +414,7 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testRestrictedEditLoggedInUsersDeletedFromStage()
|
public function testRestrictedEditLoggedInUsersDeletedFromStage()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'restrictedEditLoggedInUsers');
|
$page = $this->objFromFixture(SiteTree::class, 'restrictedEditLoggedInUsers');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
|
|
||||||
$this->logInWithPermission("ADMIN");
|
$this->logInWithPermission("ADMIN");
|
||||||
@ -421,39 +430,60 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
$subadminuser = $this->objFromFixture(Member::class, 'subadmin');
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
$page->canEdit($subadminuser),
|
$page->canEdit($subadminuser),
|
||||||
'Authenticated members can edit a page that was deleted from stage and marked as "Editable by logged in users" if they have cms permissions and belong to any of these groups'
|
'Authenticated members can edit a page that was deleted from stage and marked as "Editable by logged ' .
|
||||||
|
'in users" if they have cms permissions and belong to any of these groups'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInheritCanViewFromSiteConfig()
|
public function testInheritCanViewFromSiteConfig()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'inheritWithNoParent');
|
$page = $this->objFromFixture(SiteTree::class, 'inheritWithNoParent');
|
||||||
$siteconfig = $this->objFromFixture(SiteConfig::class, 'default');
|
$siteconfig = $this->objFromFixture(SiteConfig::class, 'default');
|
||||||
$editor = $this->objFromFixture(Member::class, 'editor');
|
$editor = $this->objFromFixture(Member::class, 'editor');
|
||||||
$editorGroup = $this->objFromFixture(Group::class, 'editorgroup');
|
$editorGroup = $this->objFromFixture(Group::class, 'editorgroup');
|
||||||
|
|
||||||
$siteconfig->CanViewType = 'Anyone';
|
$siteconfig->CanViewType = 'Anyone';
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
$this->assertTrue($page->canView(false), 'Anyone can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers');
|
$this->assertTrue(
|
||||||
|
$page->canView(false),
|
||||||
|
'Anyone can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to ' .
|
||||||
|
'LoggedInUsers'
|
||||||
|
);
|
||||||
|
|
||||||
$siteconfig->CanViewType = 'LoggedInUsers';
|
$siteconfig->CanViewType = 'LoggedInUsers';
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
$this->assertFalse($page->canView(false), 'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers');
|
$this->assertFalse(
|
||||||
|
$page->canView(false),
|
||||||
|
'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to ' .
|
||||||
|
'LoggedInUsers'
|
||||||
|
);
|
||||||
|
|
||||||
$siteconfig->CanViewType = 'LoggedInUsers';
|
$siteconfig->CanViewType = 'LoggedInUsers';
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
$this->assertTrue($page->canView($editor), 'Users can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to LoggedInUsers');
|
$this->assertTrue(
|
||||||
|
$page->canView($editor),
|
||||||
|
'Users can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to ' .
|
||||||
|
'LoggedInUsers'
|
||||||
|
);
|
||||||
|
|
||||||
$siteconfig->CanViewType = 'OnlyTheseUsers';
|
$siteconfig->CanViewType = 'OnlyTheseUsers';
|
||||||
$siteconfig->ViewerGroups()->add($editorGroup);
|
$siteconfig->ViewerGroups()->add($editorGroup);
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
$this->assertTrue($page->canView($editor), 'Editors can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to OnlyTheseUsers');
|
$this->assertTrue(
|
||||||
$this->assertFalse($page->canView(false), 'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to OnlyTheseUsers');
|
$page->canView($editor),
|
||||||
|
'Editors can view a page when set to inherit from the SiteConfig, and SiteConfig has canView set to ' .
|
||||||
|
'OnlyTheseUsers'
|
||||||
|
);
|
||||||
|
$this->assertFalse(
|
||||||
|
$page->canView(false),
|
||||||
|
'Anonymous can\'t view a page when set to inherit from the SiteConfig, and SiteConfig has canView set ' .
|
||||||
|
'to OnlyTheseUsers'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInheritCanEditFromSiteConfig()
|
public function testInheritCanEditFromSiteConfig()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture(Page::class, 'inheritWithNoParent');
|
$page = $this->objFromFixture(SiteTree::class, 'inheritWithNoParent');
|
||||||
$siteconfig = $this->objFromFixture(SiteConfig::class, 'default');
|
$siteconfig = $this->objFromFixture(SiteConfig::class, 'default');
|
||||||
$editor = $this->objFromFixture(Member::class, 'editor');
|
$editor = $this->objFromFixture(Member::class, 'editor');
|
||||||
$user = $this->objFromFixture(Member::class, 'websiteuser');
|
$user = $this->objFromFixture(Member::class, 'websiteuser');
|
||||||
@ -462,17 +492,37 @@ class SiteTreePermissionsTest extends FunctionalTest
|
|||||||
$siteconfig->CanEditType = 'LoggedInUsers';
|
$siteconfig->CanEditType = 'LoggedInUsers';
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
|
|
||||||
$this->assertFalse($page->canEdit(false), 'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to LoggedInUsers');
|
$this->assertFalse(
|
||||||
|
$page->canEdit(false),
|
||||||
|
'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set ' .
|
||||||
|
'to LoggedInUsers'
|
||||||
|
);
|
||||||
Security::setCurrentUser($editor);
|
Security::setCurrentUser($editor);
|
||||||
$this->assertTrue($page->canEdit(), 'Users can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to LoggedInUsers');
|
$this->assertTrue(
|
||||||
|
$page->canEdit(),
|
||||||
|
'Users can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to ' .
|
||||||
|
'LoggedInUsers'
|
||||||
|
);
|
||||||
|
|
||||||
$siteconfig->CanEditType = 'OnlyTheseUsers';
|
$siteconfig->CanEditType = 'OnlyTheseUsers';
|
||||||
$siteconfig->EditorGroups()->add($editorGroup);
|
$siteconfig->EditorGroups()->add($editorGroup);
|
||||||
$siteconfig->write();
|
$siteconfig->write();
|
||||||
$this->assertTrue($page->canEdit($editor), 'Editors can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers');
|
$this->assertTrue(
|
||||||
|
$page->canEdit($editor),
|
||||||
|
'Editors can edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to ' .
|
||||||
|
'OnlyTheseUsers'
|
||||||
|
);
|
||||||
Security::setCurrentUser(null);
|
Security::setCurrentUser(null);
|
||||||
$this->assertFalse($page->canEdit(false), 'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers');
|
$this->assertFalse(
|
||||||
|
$page->canEdit(false),
|
||||||
|
'Anonymous can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set ' .
|
||||||
|
'to OnlyTheseUsers'
|
||||||
|
);
|
||||||
Security::setCurrentUser($user);
|
Security::setCurrentUser($user);
|
||||||
$this->assertFalse($page->canEdit($user), 'Website user can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set to OnlyTheseUsers');
|
$this->assertFalse(
|
||||||
|
$page->canEdit($user),
|
||||||
|
'Website user can\'t edit a page when set to inherit from the SiteConfig, and SiteConfig has canEdit set ' .
|
||||||
|
'to OnlyTheseUsers'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ SilverStripe\Security\Member:
|
|||||||
Email: websiteuser@test.com
|
Email: websiteuser@test.com
|
||||||
Password: test
|
Password: test
|
||||||
Groups: =>SilverStripe\Security\Group.websiteusers
|
Groups: =>SilverStripe\Security\Group.websiteusers
|
||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
standardpage:
|
standardpage:
|
||||||
URLSegment: standardpage
|
URLSegment: standardpage
|
||||||
restrictedViewLoggedInUsers:
|
restrictedViewLoggedInUsers:
|
||||||
@ -66,7 +66,7 @@ Page:
|
|||||||
URLSegment: parent-restrictedViewOnlySubadminGroup
|
URLSegment: parent-restrictedViewOnlySubadminGroup
|
||||||
child_restrictedViewOnlySubadminGroup:
|
child_restrictedViewOnlySubadminGroup:
|
||||||
CanViewType: Inherit
|
CanViewType: Inherit
|
||||||
Parent: =>Page.parent_restrictedViewOnlySubadminGroup
|
Parent: =>SilverStripe\CMS\Model\SiteTree.parent_restrictedViewOnlySubadminGroup
|
||||||
URLSegment: child-restrictedViewOnlySubadminGroup
|
URLSegment: child-restrictedViewOnlySubadminGroup
|
||||||
parent_restrictedEditOnlySubadminGroup:
|
parent_restrictedEditOnlySubadminGroup:
|
||||||
CanEditType: OnlyTheseUsers
|
CanEditType: OnlyTheseUsers
|
||||||
@ -74,7 +74,7 @@ Page:
|
|||||||
URLSegment: parent-restrictedEditOnlySubadminGroup
|
URLSegment: parent-restrictedEditOnlySubadminGroup
|
||||||
child_restrictedEditOnlySubadminGroup:
|
child_restrictedEditOnlySubadminGroup:
|
||||||
CanEditType: Inherit
|
CanEditType: Inherit
|
||||||
Parent: =>Page.parent_restrictedEditOnlySubadminGroup
|
Parent: =>SilverStripe\CMS\Model\SiteTree.parent_restrictedEditOnlySubadminGroup
|
||||||
URLSegment: child-restrictedEditOnlySubadminGroup
|
URLSegment: child-restrictedEditOnlySubadminGroup
|
||||||
deleteTestParentPage:
|
deleteTestParentPage:
|
||||||
CanEditType: Inherit
|
CanEditType: Inherit
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use Page;
|
|
||||||
use Psr\SimpleCache\CacheInterface;
|
use Psr\SimpleCache\CacheInterface;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
@ -33,16 +32,15 @@ use SilverStripe\Security\Security;
|
|||||||
use SilverStripe\SiteConfig\SiteConfig;
|
use SilverStripe\SiteConfig\SiteConfig;
|
||||||
use SilverStripe\Subsites\Extensions\SiteTreeSubsites;
|
use SilverStripe\Subsites\Extensions\SiteTreeSubsites;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use SilverStripe\View\Parsers\Diff;
|
use SilverStripe\View\Parsers\HtmlDiff;
|
||||||
use SilverStripe\View\Parsers\ShortcodeParser;
|
use SilverStripe\View\Parsers\ShortcodeParser;
|
||||||
use SilverStripe\View\Parsers\URLSegmentFilter;
|
use SilverStripe\View\Parsers\URLSegmentFilter;
|
||||||
use SilverStripe\View\Shortcodes\EmbedShortcodeProvider;
|
use SilverStripe\View\Shortcodes\EmbedShortcodeProvider;
|
||||||
use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
|
use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
|
||||||
|
use Page;
|
||||||
|
use PageController;
|
||||||
|
|
||||||
use const RESOURCES_DIR;
|
use const RESOURCES_DIR;
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
use SilverStripe\HTML5\HTML5Value;
|
|
||||||
use SilverStripe\View\Parsers\HTMLValue;
|
|
||||||
use SilverStripe\View\Parsers\HTML4Value;
|
|
||||||
|
|
||||||
class SiteTreeTest extends SapphireTest
|
class SiteTreeTest extends SapphireTest
|
||||||
{
|
{
|
||||||
@ -86,28 +84,28 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testCreateDefaultpages()
|
public function testCreateDefaultpages()
|
||||||
{
|
{
|
||||||
$remove = SiteTree::get();
|
$remove = SiteTree::get();
|
||||||
if ($remove) {
|
if ($remove) {
|
||||||
foreach ($remove as $page) {
|
foreach ($remove as $page) {
|
||||||
$page->delete();
|
$page->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure the table is empty
|
// Make sure the table is empty
|
||||||
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0);
|
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0);
|
||||||
|
|
||||||
// Disable the creation
|
// Disable the creation
|
||||||
SiteTree::config()->create_default_pages = false;
|
SiteTree::config()->create_default_pages = false;
|
||||||
singleton(SiteTree::class)->requireDefaultRecords();
|
singleton(SiteTree::class)->requireDefaultRecords();
|
||||||
|
|
||||||
// The table should still be empty
|
// The table should still be empty
|
||||||
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0);
|
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 0);
|
||||||
|
|
||||||
// Enable the creation
|
// Enable the creation
|
||||||
SiteTree::config()->create_default_pages = true;
|
SiteTree::config()->create_default_pages = true;
|
||||||
singleton(SiteTree::class)->requireDefaultRecords();
|
singleton(SiteTree::class)->requireDefaultRecords();
|
||||||
|
|
||||||
// The table should now have three rows (home, about-us, contact-us)
|
// The table should now have three rows (home, about-us, contact-us)
|
||||||
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 3);
|
$this->assertEquals(DB::query('SELECT COUNT("ID") FROM "SiteTree"')->value(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,7 +132,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
];
|
];
|
||||||
|
|
||||||
foreach ($expectedURLs as $fixture => $urlSegment) {
|
foreach ($expectedURLs as $fixture => $urlSegment) {
|
||||||
$obj = $this->objFromFixture('Page', $fixture);
|
$obj = $this->objFromFixture(SiteTree::class, $fixture);
|
||||||
$this->assertEquals($urlSegment, $obj->URLSegment);
|
$this->assertEquals($urlSegment, $obj->URLSegment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,9 +143,9 @@ class SiteTreeTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function testDisallowedURLGeneration($title, $urlSegment)
|
public function testDisallowedURLGeneration($title, $urlSegment)
|
||||||
{
|
{
|
||||||
$page = Page::create(['Title' => $title]);
|
$page = new SiteTree(['Title' => $title]);
|
||||||
$id = $page->write();
|
$id = $page->write();
|
||||||
$page = Page::get()->byID($id);
|
$page = SiteTree::get()->byID($id);
|
||||||
$this->assertEquals($urlSegment, $page->URLSegment);
|
$this->assertEquals($urlSegment, $page->URLSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,9 +158,9 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
// Using the same dataprovider, strip out the -2 from the admin and dev segment
|
// Using the same dataprovider, strip out the -2 from the admin and dev segment
|
||||||
$urlSegment = str_replace('-2', '', $urlSegment ?? '');
|
$urlSegment = str_replace('-2', '', $urlSegment ?? '');
|
||||||
$page = Page::create(['Title' => $title, 'ParentID' => 1]);
|
$page = new SiteTree(['Title' => $title, 'ParentID' => 1]);
|
||||||
$id = $page->write();
|
$id = $page->write();
|
||||||
$page = Page::get()->byID($id);
|
$page = SiteTree::get()->byID($id);
|
||||||
$this->assertEquals($urlSegment, $page->URLSegment);
|
$this->assertEquals($urlSegment, $page->URLSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +175,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->markTestSkipped('This legacy test requires RESOURCES_DIR to be "resources"');
|
$this->markTestSkipped('This legacy test requires RESOURCES_DIR to be "resources"');
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = SiteTree::create(['Title' => 'Resources']);
|
$page = new SiteTree(['Title' => 'Resources']);
|
||||||
$id = $page->write();
|
$id = $page->write();
|
||||||
$page = SiteTree::get()->byID($id);
|
$page = SiteTree::get()->byID($id);
|
||||||
$this->assertSame('resources-2', $page->URLSegment);
|
$this->assertSame('resources-2', $page->URLSegment);
|
||||||
@ -195,7 +193,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->markTestSkipped('This test requires RESOURCES_DIR to be something other than "resources"');
|
$this->markTestSkipped('This test requires RESOURCES_DIR to be something other than "resources"');
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = SiteTree::create(['Title' => '_Resources']);
|
$page = new SiteTree(['Title' => '_Resources']);
|
||||||
$id = $page->write();
|
$id = $page->write();
|
||||||
$page = SiteTree::get()->byID($id);
|
$page = SiteTree::get()->byID($id);
|
||||||
$this->assertSame('resources', $page->URLSegment);
|
$this->assertSame('resources', $page->URLSegment);
|
||||||
@ -206,10 +204,12 @@ class SiteTreeTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function testPublishCopiesToLiveTable()
|
public function testPublishCopiesToLiveTable()
|
||||||
{
|
{
|
||||||
$obj = $this->objFromFixture('Page', 'about');
|
$obj = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$obj->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$obj->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
$createdID = DB::query("SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"URLSegment\" = '$obj->URLSegment'")->value();
|
$createdID = DB::query(
|
||||||
|
"SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"URLSegment\" = '$obj->URLSegment'"
|
||||||
|
)->value();
|
||||||
$this->assertEquals($obj->ID, $createdID);
|
$this->assertEquals($obj->ID, $createdID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,12 +220,15 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$obj = $this->objFromFixture('Page', 'about');
|
$obj = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$obj->Title = "asdfasdf";
|
$obj->Title = "asdfasdf";
|
||||||
$obj->write();
|
$obj->write();
|
||||||
$this->assertTrue($obj->publishRecursive());
|
$this->assertTrue($obj->publishRecursive());
|
||||||
|
|
||||||
$this->assertEquals('asdfasdf', DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value());
|
$this->assertEquals(
|
||||||
|
'asdfasdf',
|
||||||
|
DB::query("SELECT \"Title\" FROM \"SiteTree_Live\" WHERE \"ID\" = '$obj->ID'")->value()
|
||||||
|
);
|
||||||
|
|
||||||
$obj->Title = null;
|
$obj->Title = null;
|
||||||
$obj->write();
|
$obj->write();
|
||||||
@ -272,7 +275,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
|
|
||||||
$checkSiteTree = DataObject::get_one(SiteTree::class, [
|
$checkSiteTree = DataObject::get_one(SiteTree::class, [
|
||||||
'"SiteTree"."URLSegment"' => 'get-one-test-page'
|
'"SiteTree"."URLSegment"' => 'get-one-test-page',
|
||||||
]);
|
]);
|
||||||
$this->assertEquals("V1", $checkSiteTree->Title);
|
$this->assertEquals("V1", $checkSiteTree->Title);
|
||||||
|
|
||||||
@ -311,10 +314,13 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
/* DataObject::write() should save to a has_one relationship if you set a field called (relname)ID */
|
/* DataObject::write() should save to a has_one relationship if you set a field called (relname)ID */
|
||||||
$page = new SiteTree();
|
$page = new SiteTree();
|
||||||
$parentID = $this->idFromFixture('Page', 'home');
|
$parentID = $this->idFromFixture(SiteTree::class, 'home');
|
||||||
$page->ParentID = $parentID;
|
$page->ParentID = $parentID;
|
||||||
$page->write();
|
$page->write();
|
||||||
$this->assertEquals($parentID, DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value());
|
$this->assertEquals(
|
||||||
|
$parentID,
|
||||||
|
DB::query("SELECT \"ParentID\" FROM \"SiteTree\" WHERE \"ID\" = $page->ID")->value()
|
||||||
|
);
|
||||||
|
|
||||||
/* You should then be able to save a null/0/'' value to the relation */
|
/* You should then be able to save a null/0/'' value to the relation */
|
||||||
$page->ParentID = null;
|
$page->ParentID = null;
|
||||||
@ -398,23 +404,23 @@ class SiteTreeTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function testRestoreToStage()
|
public function testRestoreToStage()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture('Page', 'about');
|
$page = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageID = $page->ID;
|
$pageID = $page->ID;
|
||||||
$page->delete();
|
$page->delete();
|
||||||
$this->assertTrue(!DataObject::get_by_id("Page", $pageID));
|
$this->assertTrue(!DataObject::get_by_id(SiteTree::class, $pageID));
|
||||||
|
|
||||||
$deletedPage = Versioned::get_latest_version(SiteTree::class, $pageID);
|
$deletedPage = Versioned::get_latest_version(SiteTree::class, $pageID);
|
||||||
$resultPage = $deletedPage->doRestoreToStage();
|
$resultPage = $deletedPage->doRestoreToStage();
|
||||||
|
|
||||||
$requeriedPage = DataObject::get_by_id("Page", $pageID);
|
$requeriedPage = DataObject::get_by_id(SiteTree::class, $pageID);
|
||||||
|
|
||||||
$this->assertEquals($pageID, $resultPage->ID);
|
$this->assertEquals($pageID, $resultPage->ID);
|
||||||
$this->assertEquals($pageID, $requeriedPage->ID);
|
$this->assertEquals($pageID, $requeriedPage->ID);
|
||||||
$this->assertEquals('About Us', $requeriedPage->Title);
|
$this->assertEquals('About Us', $requeriedPage->Title);
|
||||||
$this->assertInstanceOf('Page', $requeriedPage);
|
$this->assertInstanceOf(SiteTree::class, $requeriedPage);
|
||||||
|
|
||||||
|
|
||||||
$page2 = $this->objFromFixture('Page', 'products');
|
$page2 = $this->objFromFixture(SiteTree::class, 'products');
|
||||||
$page2ID = $page2->ID;
|
$page2ID = $page2->ID;
|
||||||
$page2->doUnpublish();
|
$page2->doUnpublish();
|
||||||
$page2->delete();
|
$page2->delete();
|
||||||
@ -424,12 +430,14 @@ class SiteTreeTest extends SapphireTest
|
|||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$deletedPage = Versioned::get_latest_version(SiteTree::class, $page2ID);
|
$deletedPage = Versioned::get_latest_version(SiteTree::class, $page2ID);
|
||||||
$deletedPage->doRestoreToStage();
|
$deletedPage->doRestoreToStage();
|
||||||
$this->assertFalse((bool)Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, "\"SiteTree\".\"ID\" = " . $page2ID));
|
$this->assertFalse(
|
||||||
|
(bool)Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, "\"SiteTree\".\"ID\" = " . $page2ID)
|
||||||
|
);
|
||||||
|
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
$requeriedPage = DataObject::get_by_id("Page", $page2ID);
|
$requeriedPage = DataObject::get_by_id(SiteTree::class, $page2ID);
|
||||||
$this->assertEquals('Products', $requeriedPage->Title);
|
$this->assertEquals('Products', $requeriedPage->Title);
|
||||||
$this->assertInstanceOf('Page', $requeriedPage);
|
$this->assertInstanceOf(SiteTree::class, $requeriedPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNoCascadingDeleteWithoutID()
|
public function testNoCascadingDeleteWithoutID()
|
||||||
@ -453,10 +461,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testGetByLink()
|
public function testGetByLink()
|
||||||
{
|
{
|
||||||
$home = $this->objFromFixture('Page', 'home');
|
$home = $this->objFromFixture(SiteTree::class, 'home');
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$product = $this->objFromFixture('Page', 'product1');
|
$product = $this->objFromFixture(SiteTree::class, 'product1');
|
||||||
|
|
||||||
SiteTree::config()->nested_urls = false;
|
SiteTree::config()->nested_urls = false;
|
||||||
|
|
||||||
@ -483,10 +491,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testGetByLinkAbsolute()
|
public function testGetByLinkAbsolute()
|
||||||
{
|
{
|
||||||
$home = $this->objFromFixture('Page', 'home');
|
$home = $this->objFromFixture(SiteTree::class, 'home');
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$product = $this->objFromFixture('Page', 'product1');
|
$product = $this->objFromFixture(SiteTree::class, 'product1');
|
||||||
|
|
||||||
$base = 'https://example.test/';
|
$base = 'https://example.test/';
|
||||||
$this->assertEquals($home->ID, SiteTree::get_by_link(Controller::join_links($base, '/'), false)->ID);
|
$this->assertEquals($home->ID, SiteTree::get_by_link(Controller::join_links($base, '/'), false)->ID);
|
||||||
@ -498,29 +506,45 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testRelativeLink()
|
public function testRelativeLink()
|
||||||
{
|
{
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
|
|
||||||
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
||||||
|
|
||||||
$this->assertEquals('about-us/', $about->RelativeLink(), 'Matches URLSegment on top level without parameters');
|
$this->assertEquals(
|
||||||
$this->assertEquals('about-us/my-staff/', $staff->RelativeLink(), 'Matches URLSegment plus parent on second level without parameters');
|
'about-us',
|
||||||
$this->assertEquals('about-us/edit', $about->RelativeLink('edit'), 'Matches URLSegment plus parameter on top level');
|
$about->RelativeLink(),
|
||||||
$this->assertEquals('about-us/tom&jerry', $about->RelativeLink('tom&jerry'), 'Doesnt url encode parameter');
|
'Matches URLSegment on top level without parameters'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'about-us/my-staff',
|
||||||
|
$staff->RelativeLink(),
|
||||||
|
'Matches URLSegment plus parent on second level without parameters'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'about-us/edit',
|
||||||
|
$about->RelativeLink('edit'),
|
||||||
|
'Matches URLSegment plus parameter on top level'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
'about-us/tom&jerry',
|
||||||
|
$about->RelativeLink('tom&jerry'),
|
||||||
|
'Doesnt url encode parameter'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPageLevel()
|
public function testPageLevel()
|
||||||
{
|
{
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$this->assertEquals(1, $about->getPageLevel());
|
$this->assertEquals(1, $about->getPageLevel());
|
||||||
$this->assertEquals(2, $staff->getPageLevel());
|
$this->assertEquals(2, $staff->getPageLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAbsoluteLiveLink()
|
public function testAbsoluteLiveLink()
|
||||||
{
|
{
|
||||||
$parent = $this->objFromFixture('Page', 'about');
|
$parent = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$child = $this->objFromFixture('Page', 'staff');
|
$child = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
|
|
||||||
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
Config::modify()->set(SiteTree::class, 'nested_urls', true);
|
||||||
|
|
||||||
@ -531,23 +555,23 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$parent->URLSegment = 'changed-on-draft';
|
$parent->URLSegment = 'changed-on-draft';
|
||||||
$parent->write();
|
$parent->write();
|
||||||
|
|
||||||
$this->assertStringEndsWith('changed-on-live/my-staff/', $child->getAbsoluteLiveLink(false));
|
$this->assertStringEndsWith('changed-on-live/my-staff', $child->getAbsoluteLiveLink(false));
|
||||||
$this->assertStringEndsWith('changed-on-live/my-staff/?stage=Live', $child->getAbsoluteLiveLink());
|
$this->assertStringEndsWith('changed-on-live/my-staff?stage=Live', $child->getAbsoluteLiveLink());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDuplicateChildrenRetainSort()
|
public function testDuplicateChildrenRetainSort()
|
||||||
{
|
{
|
||||||
$parent = new Page();
|
$parent = new SiteTree();
|
||||||
$parent->Title = 'Parent';
|
$parent->Title = 'Parent';
|
||||||
$parent->write();
|
$parent->write();
|
||||||
|
|
||||||
$child1 = new Page();
|
$child1 = new SiteTree();
|
||||||
$child1->ParentID = $parent->ID;
|
$child1->ParentID = $parent->ID;
|
||||||
$child1->Title = 'Child 1';
|
$child1->Title = 'Child 1';
|
||||||
$child1->Sort = 2;
|
$child1->Sort = 2;
|
||||||
$child1->write();
|
$child1->write();
|
||||||
|
|
||||||
$child2 = new Page();
|
$child2 = new SiteTree();
|
||||||
$child2->ParentID = $parent->ID;
|
$child2->ParentID = $parent->ID;
|
||||||
$child2->Title = 'Child 2';
|
$child2->Title = 'Child 2';
|
||||||
$child2->Sort = 1;
|
$child2->Sort = 1;
|
||||||
@ -571,34 +595,34 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testDeleteFromStageOperatesRecursively()
|
public function testDeleteFromStageOperatesRecursively()
|
||||||
{
|
{
|
||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageStaff = $this->objFromFixture('Page', 'staff');
|
$pageStaff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
$pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate');
|
||||||
|
|
||||||
$pageAbout->delete();
|
$pageAbout->delete();
|
||||||
|
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID));
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaff->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree);
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaffDuplicate->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree);
|
||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeleteFromStageOperatesRecursivelyStrict()
|
public function testDeleteFromStageOperatesRecursivelyStrict()
|
||||||
{
|
{
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageStaff = $this->objFromFixture('Page', 'staff');
|
$pageStaff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
$pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate');
|
||||||
|
|
||||||
$pageAbout->delete();
|
$pageAbout->delete();
|
||||||
|
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID));
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageStaff->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaff->ID));
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageStaffDuplicate->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDuplicate()
|
public function testDuplicate()
|
||||||
{
|
{
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$dupe = $pageAbout->duplicate();
|
$dupe = $pageAbout->duplicate();
|
||||||
$this->assertEquals($pageAbout->Title, $dupe->Title);
|
$this->assertEquals($pageAbout->Title, $dupe->Title);
|
||||||
$this->assertNotEquals($pageAbout->URLSegment, $dupe->URLSegment);
|
$this->assertNotEquals($pageAbout->URLSegment, $dupe->URLSegment);
|
||||||
@ -610,22 +634,22 @@ class SiteTreeTest extends SapphireTest
|
|||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageAbout->publishRecursive();
|
$pageAbout->publishRecursive();
|
||||||
$pageStaff = $this->objFromFixture('Page', 'staff');
|
$pageStaff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$pageStaff->publishRecursive();
|
$pageStaff->publishRecursive();
|
||||||
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
$pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate');
|
||||||
$pageStaffDuplicate->publishRecursive();
|
$pageStaffDuplicate->publishRecursive();
|
||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'about');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
|
|
||||||
$parentPage->doUnpublish();
|
$parentPage->doUnpublish();
|
||||||
|
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
|
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID));
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaff->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree);
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaffDuplicate->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree);
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
||||||
}
|
}
|
||||||
@ -635,20 +659,20 @@ class SiteTreeTest extends SapphireTest
|
|||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', false);
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageAbout->publishRecursive();
|
$pageAbout->publishRecursive();
|
||||||
$pageStaff = $this->objFromFixture('Page', 'staff');
|
$pageStaff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$pageStaff->publishRecursive();
|
$pageStaff->publishRecursive();
|
||||||
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
$pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate');
|
||||||
$pageStaffDuplicate->publishRecursive();
|
$pageStaffDuplicate->publishRecursive();
|
||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'about');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$parentPage->doUnpublish();
|
$parentPage->doUnpublish();
|
||||||
|
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID));
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaff->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaff->ID) instanceof SiteTree);
|
||||||
$this->assertTrue(DataObject::get_by_id('Page', $pageStaffDuplicate->ID) instanceof Page);
|
$this->assertTrue(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID) instanceof SiteTree);
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
Config::modify()->set(SiteTree::class, 'enforce_strict_hierarchy', true);
|
||||||
}
|
}
|
||||||
@ -657,20 +681,20 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
$pageAbout = $this->objFromFixture('Page', 'about');
|
$pageAbout = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$pageAbout->publishRecursive();
|
$pageAbout->publishRecursive();
|
||||||
$pageStaff = $this->objFromFixture('Page', 'staff');
|
$pageStaff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$pageStaff->publishRecursive();
|
$pageStaff->publishRecursive();
|
||||||
$pageStaffDuplicate = $this->objFromFixture('Page', 'staffduplicate');
|
$pageStaffDuplicate = $this->objFromFixture(SiteTree::class, 'staffduplicate');
|
||||||
$pageStaffDuplicate->publishRecursive();
|
$pageStaffDuplicate->publishRecursive();
|
||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'about');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$parentPage->doUnpublish();
|
$parentPage->doUnpublish();
|
||||||
|
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageAbout->ID));
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageStaff->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaff->ID));
|
||||||
$this->assertNull(DataObject::get_by_id('Page', $pageStaffDuplicate->ID));
|
$this->assertNull(DataObject::get_by_id(SiteTree::class, $pageStaffDuplicate->ID));
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +705,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testReadArchiveDate()
|
public function testReadArchiveDate()
|
||||||
{
|
{
|
||||||
DBDatetime::set_mock_now('2009-07-02 14:05:07');
|
DBDatetime::set_mock_now('2009-07-02 14:05:07');
|
||||||
$oldPage = SiteTree::create();
|
$oldPage = new SiteTree();
|
||||||
$oldPage->Title = 'A really old page';
|
$oldPage->Title = 'A really old page';
|
||||||
$oldPage->write();
|
$oldPage->write();
|
||||||
DBDatetime::clear_mock_now();
|
DBDatetime::clear_mock_now();
|
||||||
@ -689,7 +713,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$date = '2009-07-02 14:05:07';
|
$date = '2009-07-02 14:05:07';
|
||||||
Versioned::reading_archived_date($date);
|
Versioned::reading_archived_date($date);
|
||||||
$result = SiteTree::get()->where([
|
$result = SiteTree::get()->where([
|
||||||
'"SiteTree"."ParentID"' => 0
|
'"SiteTree"."ParentID"' => 0,
|
||||||
]);
|
]);
|
||||||
$this->assertCount(1, $result, '"A really old page" should be returned');
|
$this->assertCount(1, $result, '"A really old page" should be returned');
|
||||||
}
|
}
|
||||||
@ -698,11 +722,11 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$editor = $this->objFromFixture(Member::class, "editor");
|
$editor = $this->objFromFixture(Member::class, "editor");
|
||||||
|
|
||||||
$home = $this->objFromFixture("Page", "home");
|
$home = $this->objFromFixture(SiteTree::class, "home");
|
||||||
$staff = $this->objFromFixture("Page", "staff");
|
$staff = $this->objFromFixture(SiteTree::class, "staff");
|
||||||
$products = $this->objFromFixture("Page", "products");
|
$products = $this->objFromFixture(SiteTree::class, "products");
|
||||||
$product1 = $this->objFromFixture("Page", "product1");
|
$product1 = $this->objFromFixture(SiteTree::class, "product1");
|
||||||
$product4 = $this->objFromFixture("Page", "product4");
|
$product4 = $this->objFromFixture(SiteTree::class, "product4");
|
||||||
|
|
||||||
// Test logged out users cannot edit
|
// Test logged out users cannot edit
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
@ -723,7 +747,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testCanEditWithAccessToAllSections()
|
public function testCanEditWithAccessToAllSections()
|
||||||
{
|
{
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->write();
|
$page->write();
|
||||||
$allSectionMember = $this->objFromFixture(Member::class, 'allsections');
|
$allSectionMember = $this->objFromFixture(Member::class, 'allsections');
|
||||||
$securityAdminMember = $this->objFromFixture(Member::class, 'securityadmin');
|
$securityAdminMember = $this->objFromFixture(Member::class, 'securityadmin');
|
||||||
@ -748,7 +772,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->assertTrue(singleton(SiteTree::class)->canCreate());
|
$this->assertTrue(singleton(SiteTree::class)->canCreate());
|
||||||
|
|
||||||
// Test creation underneath a parent which this user doesn't have access to
|
// Test creation underneath a parent which this user doesn't have access to
|
||||||
$parent = $this->objFromFixture('Page', 'about');
|
$parent = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$this->assertFalse(singleton(SiteTree::class)->canCreate(null, ['Parent' => $parent]));
|
$this->assertFalse(singleton(SiteTree::class)->canCreate(null, ['Parent' => $parent]));
|
||||||
|
|
||||||
// Test creation underneath a parent which doesn't allow a certain child
|
// Test creation underneath a parent which doesn't allow a certain child
|
||||||
@ -764,13 +788,18 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->assertTrue(singleton(SiteTree::class)->canCreate(null, ['Parent' => singleton(SiteTree::class)]));
|
$this->assertTrue(singleton(SiteTree::class)->canCreate(null, ['Parent' => singleton(SiteTree::class)]));
|
||||||
|
|
||||||
//Test we don't check for allowedChildren on parent context if it's not SiteTree instance
|
//Test we don't check for allowedChildren on parent context if it's not SiteTree instance
|
||||||
$this->assertTrue(singleton(SiteTree::class)->canCreate(null, ['Parent' => $this->objFromFixture(SiteTreeTest_DataObject::class, 'relations')]));
|
$this->assertTrue(
|
||||||
|
singleton(SiteTree::class)->canCreate(
|
||||||
|
null,
|
||||||
|
['Parent' => $this->objFromFixture(SiteTreeTest_DataObject::class, 'relations')]
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEditPermissionsOnDraftVsLive()
|
public function testEditPermissionsOnDraftVsLive()
|
||||||
{
|
{
|
||||||
// Create an inherit-permission page
|
// Create an inherit-permission page
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->write();
|
$page->write();
|
||||||
$page->CanEditType = "Inherit";
|
$page->CanEditType = "Inherit";
|
||||||
$page->publishRecursive();
|
$page->publishRecursive();
|
||||||
@ -818,10 +847,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testCompareVersions()
|
public function testCompareVersions()
|
||||||
{
|
{
|
||||||
// Necessary to avoid
|
// Necessary to avoid
|
||||||
$oldCleanerClass = Diff::$html_cleaner_class;
|
$oldCleanerClass = HtmlDiff::$html_cleaner_class;
|
||||||
Diff::$html_cleaner_class = SiteTreeTest_NullHtmlCleaner::class;
|
HtmlDiff::$html_cleaner_class = SiteTreeTest_NullHtmlCleaner::class;
|
||||||
|
|
||||||
$page = new Page();
|
$page = new SiteTree();
|
||||||
$page->write();
|
$page->write();
|
||||||
$this->assertEquals(1, $page->Version);
|
$this->assertEquals(1, $page->Version);
|
||||||
|
|
||||||
@ -839,7 +868,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$processedContent = preg_replace('/>\s*/', '>', $processedContent ?? '');
|
$processedContent = preg_replace('/>\s*/', '>', $processedContent ?? '');
|
||||||
$this->assertEquals("<ins><span>This is a test</span></ins>", $processedContent);
|
$this->assertEquals("<ins><span>This is a test</span></ins>", $processedContent);
|
||||||
|
|
||||||
Diff::$html_cleaner_class = $oldCleanerClass;
|
HtmlDiff::$html_cleaner_class = $oldCleanerClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAuthorIDAndPublisherIDFilledOutOnPublish()
|
public function testAuthorIDAndPublisherIDFilledOutOnPublish()
|
||||||
@ -849,16 +878,16 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->logInAs($member);
|
$this->logInAs($member);
|
||||||
|
|
||||||
// Write the page
|
// Write the page
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$about->Title = "Another title";
|
$about->Title = "Another title";
|
||||||
$about->write();
|
$about->write();
|
||||||
|
|
||||||
// Check the version created
|
// Check the version created
|
||||||
$savedVersion = DB::prepared_query(
|
$savedVersion = DB::prepared_query(
|
||||||
"SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\"
|
"SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\"
|
||||||
WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC",
|
WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC",
|
||||||
[$about->ID]
|
[$about->ID]
|
||||||
)->first();
|
)->record();
|
||||||
$this->assertEquals($member->ID, $savedVersion['AuthorID']);
|
$this->assertEquals($member->ID, $savedVersion['AuthorID']);
|
||||||
$this->assertEquals(0, $savedVersion['PublisherID']);
|
$this->assertEquals(0, $savedVersion['PublisherID']);
|
||||||
|
|
||||||
@ -866,9 +895,9 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$about->publishRecursive();
|
$about->publishRecursive();
|
||||||
$publishedVersion = DB::prepared_query(
|
$publishedVersion = DB::prepared_query(
|
||||||
"SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\"
|
"SELECT \"AuthorID\", \"PublisherID\" FROM \"SiteTree_Versions\"
|
||||||
WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC",
|
WHERE \"RecordID\" = ? ORDER BY \"Version\" DESC",
|
||||||
[$about->ID]
|
[$about->ID]
|
||||||
)->first();
|
)->record();
|
||||||
|
|
||||||
// Check the version created
|
// Check the version created
|
||||||
$this->assertEquals($member->ID, $publishedVersion['AuthorID']);
|
$this->assertEquals($member->ID, $publishedVersion['AuthorID']);
|
||||||
@ -877,7 +906,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testLinkShortcodeHandler()
|
public function testLinkShortcodeHandler()
|
||||||
{
|
{
|
||||||
$aboutPage = $this->objFromFixture('Page', 'about');
|
$aboutPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$redirectPage = $this->objFromFixture(RedirectorPage::class, 'external');
|
$redirectPage = $this->objFromFixture(RedirectorPage::class, 'external');
|
||||||
|
|
||||||
$parser = new ShortcodeParser();
|
$parser = new ShortcodeParser();
|
||||||
@ -889,12 +918,24 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$aboutShortcodeExpected = $aboutPage->Link();
|
$aboutShortcodeExpected = $aboutPage->Link();
|
||||||
$aboutEnclosedExpected = sprintf('<a href="%s">Example Content</a>', $aboutPage->Link());
|
$aboutEnclosedExpected = sprintf('<a href="%s">Example Content</a>', $aboutPage->Link());
|
||||||
|
|
||||||
$this->assertEquals($aboutShortcodeExpected, $parser->parse($aboutShortcode), 'Test that simple linking works.');
|
$this->assertEquals(
|
||||||
$this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed), 'Test enclosed content is linked.');
|
$aboutShortcodeExpected,
|
||||||
|
$parser->parse($aboutShortcode),
|
||||||
|
'Test that simple linking works.'
|
||||||
|
);
|
||||||
|
$this->assertEquals(
|
||||||
|
$aboutEnclosedExpected,
|
||||||
|
$parser->parse($aboutEnclosed),
|
||||||
|
'Test enclosed content is linked.'
|
||||||
|
);
|
||||||
|
|
||||||
$aboutPage->delete();
|
$aboutPage->delete();
|
||||||
|
|
||||||
$this->assertEquals($aboutShortcodeExpected, $parser->parse($aboutShortcode), 'Test that deleted pages still link.');
|
$this->assertEquals(
|
||||||
|
$aboutShortcodeExpected,
|
||||||
|
$parser->parse($aboutShortcode),
|
||||||
|
'Test that deleted pages still link.'
|
||||||
|
);
|
||||||
$this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed));
|
$this->assertEquals($aboutEnclosedExpected, $parser->parse($aboutEnclosed));
|
||||||
|
|
||||||
$aboutShortcode = '[sitetree_link,id="-1"]';
|
$aboutShortcode = '[sitetree_link,id="-1"]';
|
||||||
@ -908,7 +949,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$redirectExpected = 'http://www.google.com?a&b';
|
$redirectExpected = 'http://www.google.com?a&b';
|
||||||
|
|
||||||
$this->assertEquals($redirectExpected, $parser->parse($redirectShortcode));
|
$this->assertEquals($redirectExpected, $parser->parse($redirectShortcode));
|
||||||
$this->assertEquals(sprintf('<a href="%s">Example Content</a>', $redirectExpected), $parser->parse($redirectEnclosed));
|
$this->assertEquals(
|
||||||
|
sprintf('<a href="%s">Example Content</a>', $redirectExpected),
|
||||||
|
$parser->parse($redirectEnclosed)
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals('', $parser->parse('[sitetree_link]'), 'Test that invalid ID attributes are not parsed.');
|
$this->assertEquals('', $parser->parse('[sitetree_link]'), 'Test that invalid ID attributes are not parsed.');
|
||||||
$this->assertEquals('', $parser->parse('[sitetree_link,id="text"]'));
|
$this->assertEquals('', $parser->parse('[sitetree_link,id="text"]'));
|
||||||
@ -917,8 +961,8 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testIsCurrent()
|
public function testIsCurrent()
|
||||||
{
|
{
|
||||||
$aboutPage = $this->objFromFixture('Page', 'about');
|
$aboutPage = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$productPage = $this->objFromFixture('Page', 'products');
|
$productPage = $this->objFromFixture(SiteTree::class, 'products');
|
||||||
|
|
||||||
Director::set_current_page($aboutPage);
|
Director::set_current_page($aboutPage);
|
||||||
$this->assertTrue($aboutPage->isCurrent(), 'Assert that basic isCurrent checks works.');
|
$this->assertTrue($aboutPage->isCurrent(), 'Assert that basic isCurrent checks works.');
|
||||||
@ -926,7 +970,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
$this->assertTrue(
|
$this->assertTrue(
|
||||||
DataObject::get_one(SiteTree::class, [
|
DataObject::get_one(SiteTree::class, [
|
||||||
'"SiteTree"."Title"' => 'About Us'
|
'"SiteTree"."Title"' => 'About Us',
|
||||||
])->isCurrent(),
|
])->isCurrent(),
|
||||||
'Assert that isCurrent works on another instance with the same ID.'
|
'Assert that isCurrent works on another instance with the same ID.'
|
||||||
);
|
);
|
||||||
@ -937,9 +981,9 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testIsSection()
|
public function testIsSection()
|
||||||
{
|
{
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$ceo = $this->objFromFixture('Page', 'ceo');
|
$ceo = $this->objFromFixture(SiteTree::class, 'ceo');
|
||||||
|
|
||||||
Director::set_current_page($about);
|
Director::set_current_page($about);
|
||||||
$this->assertTrue($about->isSection());
|
$this->assertTrue($about->isSection());
|
||||||
@ -959,7 +1003,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testURLSegmentReserved()
|
public function testURLSegmentReserved()
|
||||||
{
|
{
|
||||||
$siteTree = SiteTree::create(['URLSegment' => 'admin']);
|
$siteTree = new SiteTree(['URLSegment' => 'admin']);
|
||||||
$segment = $siteTree->validURLSegment();
|
$segment = $siteTree->validURLSegment();
|
||||||
|
|
||||||
$this->assertFalse($segment);
|
$this->assertFalse($segment);
|
||||||
@ -1047,7 +1091,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$sitetree->URLSegment = 'home-noconflict';
|
$sitetree->URLSegment = 'home-noconflict';
|
||||||
$this->assertTrue($sitetree->validURLSegment());
|
$this->assertTrue($sitetree->validURLSegment());
|
||||||
|
|
||||||
$sitetree->ParentID = $this->idFromFixture('Page', 'about');
|
$sitetree->ParentID = $this->idFromFixture(SiteTree::class, 'about');
|
||||||
$sitetree->URLSegment = 'home';
|
$sitetree->URLSegment = 'home';
|
||||||
$this->assertFalse($sitetree->validURLSegment(), 'Conflicts are still recognised with a ParentID value');
|
$this->assertFalse($sitetree->validURLSegment(), 'Conflicts are still recognised with a ParentID value');
|
||||||
|
|
||||||
@ -1057,7 +1101,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$sitetree->URLSegment = 'home';
|
$sitetree->URLSegment = 'home';
|
||||||
$this->assertFalse($sitetree->validURLSegment(), 'URLSegment conflicts are recognised');
|
$this->assertFalse($sitetree->validURLSegment(), 'URLSegment conflicts are recognised');
|
||||||
|
|
||||||
$sitetree->ParentID = $this->idFromFixture('Page', 'about');
|
$sitetree->ParentID = $this->idFromFixture(SiteTree::class, 'about');
|
||||||
$this->assertTrue($sitetree->validURLSegment(), 'URLSegments can be the same across levels');
|
$this->assertTrue($sitetree->validURLSegment(), 'URLSegments can be the same across levels');
|
||||||
|
|
||||||
$sitetree->URLSegment = 'my-staff';
|
$sitetree->URLSegment = 'my-staff';
|
||||||
@ -1127,13 +1171,18 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$sitetree->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$sitetree->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
$sitetree = DataObject::get_by_id(SiteTree::class, $sitetree->ID, false);
|
$sitetree = DataObject::get_by_id(SiteTree::class, $sitetree->ID, false);
|
||||||
$this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen'));
|
$this->assertEquals($sitetree->URLSegment, rawurlencode('brötchen'));
|
||||||
$sitetreeLive = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, '"SiteTree"."ID" = ' .$sitetree->ID, false);
|
$sitetreeLive = Versioned::get_one_by_stage(
|
||||||
|
SiteTree::class,
|
||||||
|
Versioned::LIVE,
|
||||||
|
'"SiteTree"."ID" = ' . $sitetree->ID,
|
||||||
|
false
|
||||||
|
);
|
||||||
$this->assertEquals($sitetreeLive->URLSegment, rawurlencode('brötchen'));
|
$this->assertEquals($sitetreeLive->URLSegment, rawurlencode('brötchen'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testVersionsAreCreated()
|
public function testVersionsAreCreated()
|
||||||
{
|
{
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Content = "one";
|
$p->Content = "one";
|
||||||
$p->write();
|
$p->write();
|
||||||
$this->assertEquals(1, $p->Version);
|
$this->assertEquals(1, $p->Version);
|
||||||
@ -1221,23 +1270,23 @@ class SiteTreeTest extends SapphireTest
|
|||||||
// Expected
|
// Expected
|
||||||
[ SiteTreeTest_ClassB::class ],
|
[ SiteTreeTest_ClassB::class ],
|
||||||
// Assertion message
|
// Assertion message
|
||||||
'Direct setting of allowed children'
|
'Direct setting of allowed children',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
SiteTreeTest_ClassB::class,
|
SiteTreeTest_ClassB::class,
|
||||||
[ SiteTreeTest_ClassC::class, SiteTreeTest_ClassCext::class ],
|
[ SiteTreeTest_ClassC::class, SiteTreeTest_ClassCext::class ],
|
||||||
'Includes subclasses'
|
'Includes subclasses',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
SiteTreeTest_ClassC::class,
|
SiteTreeTest_ClassC::class,
|
||||||
[],
|
[],
|
||||||
'Null setting'
|
'Null setting',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
SiteTreeTest_ClassD::class,
|
SiteTreeTest_ClassD::class,
|
||||||
[SiteTreeTest_ClassC::class],
|
[SiteTreeTest_ClassC::class],
|
||||||
'Excludes subclasses if class is prefixed by an asterisk'
|
'Excludes subclasses if class is prefixed by an asterisk',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,7 +1327,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
$classCext->ParentID = $classD->ID;
|
$classCext->ParentID = $classD->ID;
|
||||||
$valid = $classCext->validate();
|
$valid = $classCext->validate();
|
||||||
$this->assertFalse($valid->isValid(), "Doesnt allow child where only parent class is allowed on parent node, and asterisk prefixing is used");
|
$this->assertFalse(
|
||||||
|
$valid->isValid(),
|
||||||
|
"Doesnt allow child where only parent class is allowed on parent node, and asterisk prefixing is used"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testClassDropdown()
|
public function testClassDropdown()
|
||||||
@ -1297,8 +1349,8 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->assertArrayHasKey(SiteTreeTest_ClassA::class, $method->invoke($sitetree));
|
$this->assertArrayHasKey(SiteTreeTest_ClassA::class, $method->invoke($sitetree));
|
||||||
|
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$rootPage = $this->objFromFixture(Page::class, 'home');
|
$rootPage = $this->objFromFixture(SiteTree::class, 'home');
|
||||||
$nonRootPage = $this->objFromFixture(Page::class, 'staff');
|
$nonRootPage = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
|
|
||||||
$this->assertArrayNotHasKey(SiteTreeTest_NotRoot::class, $method->invoke($rootPage));
|
$this->assertArrayNotHasKey(SiteTreeTest_NotRoot::class, $method->invoke($rootPage));
|
||||||
$this->assertArrayHasKey(SiteTreeTest_NotRoot::class, $method->invoke($nonRootPage));
|
$this->assertArrayHasKey(SiteTreeTest_NotRoot::class, $method->invoke($nonRootPage));
|
||||||
@ -1394,11 +1446,11 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
public function testGetBreadcrumbItems()
|
public function testGetBreadcrumbItems()
|
||||||
{
|
{
|
||||||
$page = $this->objFromFixture("Page", "breadcrumbs");
|
$page = $this->objFromFixture(SiteTree::class, "breadcrumbs");
|
||||||
$this->assertEquals(1, $page->getBreadcrumbItems()->count(), "Only display current page.");
|
$this->assertEquals(1, $page->getBreadcrumbItems()->count(), "Only display current page.");
|
||||||
|
|
||||||
// Test breadcrumb order
|
// Test breadcrumb order
|
||||||
$page = $this->objFromFixture("Page", "breadcrumbs5");
|
$page = $this->objFromFixture(SiteTree::class, "breadcrumbs5");
|
||||||
$breadcrumbs = $page->getBreadcrumbItems();
|
$breadcrumbs = $page->getBreadcrumbItems();
|
||||||
$this->assertEquals($breadcrumbs->count(), 5, "Display all breadcrumbs");
|
$this->assertEquals($breadcrumbs->count(), 5, "Display all breadcrumbs");
|
||||||
$this->assertEquals($breadcrumbs->first()->Title, "Breadcrumbs", "Breadcrumbs should be the first item.");
|
$this->assertEquals($breadcrumbs->first()->Title, "Breadcrumbs", "Breadcrumbs should be the first item.");
|
||||||
@ -1418,16 +1470,16 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testMetaTags()
|
public function testMetaTags()
|
||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$page = $this->objFromFixture('Page', 'metapage');
|
$page = $this->objFromFixture(SiteTree::class, 'metapage');
|
||||||
|
|
||||||
// Test with title
|
// Test with title
|
||||||
$meta = $page->MetaTags();
|
$meta = $page->MetaTags();
|
||||||
$charset = Config::inst()->get(ContentNegotiator::class, 'encoding');
|
$charset = Config::inst()->get(ContentNegotiator::class, 'encoding');
|
||||||
$this->assertStringContainsString('<meta http-equiv="Content-Type" content="text/html; charset='.$charset.'"', $meta);
|
$this->assertStringContainsString('<meta http-equiv="Content-Type" content="text/html; charset=' . $charset . '"', $meta);
|
||||||
$this->assertStringContainsString('<meta name="description" content="The <br /> and <br> tags"', $meta);
|
$this->assertStringContainsString('<meta name="description" content="The <br /> and <br> tags"', $meta);
|
||||||
$this->assertStringContainsString('<link rel="canonical" href="http://www.mysite.com/html-and-xml"', $meta);
|
$this->assertStringContainsString('<link rel="canonical" href="http://www.mysite.com/html-and-xml"', $meta);
|
||||||
$this->assertStringContainsString('<meta name="x-page-id" content="'.$page->ID.'"', $meta);
|
$this->assertStringContainsString('<meta name="x-page-id" content="' . $page->ID.'"', $meta);
|
||||||
$this->assertStringContainsString('<meta name="x-cms-edit-link" content="'.$page->CMSEditLink().'"', $meta);
|
$this->assertStringContainsString('<meta name="x-cms-edit-link" content="' . $page->CMSEditLink().'"', $meta);
|
||||||
$this->assertStringContainsString('<title>HTML & XML</title>', $meta);
|
$this->assertStringContainsString('<title>HTML & XML</title>', $meta);
|
||||||
|
|
||||||
// Test without title
|
// Test without title
|
||||||
@ -1442,7 +1494,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
/** @var SiteTree $page */
|
/** @var SiteTree $page */
|
||||||
$page = $this->objFromFixture('Page', 'metapage');
|
$page = $this->objFromFixture(SiteTree::class, 'metapage');
|
||||||
|
|
||||||
$charset = Config::inst()->get(ContentNegotiator::class, 'encoding');
|
$charset = Config::inst()->get(ContentNegotiator::class, 'encoding');
|
||||||
|
|
||||||
@ -1524,8 +1576,8 @@ class SiteTreeTest extends SapphireTest
|
|||||||
|
|
||||||
// both pages are viewable in stage
|
// both pages are viewable in stage
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$this->assertFalse($about->isOrphaned());
|
$this->assertFalse($about->isOrphaned());
|
||||||
$this->assertFalse($staff->isOrphaned());
|
$this->assertFalse($staff->isOrphaned());
|
||||||
$this->assertTrue($about->canView($member));
|
$this->assertTrue($about->canView($member));
|
||||||
@ -1536,23 +1588,23 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->assertFalse($staff->isOrphaned());
|
$this->assertFalse($staff->isOrphaned());
|
||||||
$this->assertTrue($staff->canView($member));
|
$this->assertTrue($staff->canView($member));
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$staff = $this->objFromFixture('Page', 'staff'); // Live copy of page
|
$staff = $this->objFromFixture(SiteTree::class, 'staff'); // Live copy of page
|
||||||
$this->assertTrue($staff->isOrphaned()); // because parent isn't published
|
$this->assertTrue($staff->isOrphaned()); // because parent isn't published
|
||||||
$this->assertFalse($staff->canView($member));
|
$this->assertFalse($staff->canView($member));
|
||||||
|
|
||||||
// Publishing the parent page should restore visibility
|
// Publishing the parent page should restore visibility
|
||||||
Versioned::set_stage(Versioned::DRAFT);
|
Versioned::set_stage(Versioned::DRAFT);
|
||||||
$about = $this->objFromFixture('Page', 'about');
|
$about = $this->objFromFixture(SiteTree::class, 'about');
|
||||||
$about->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$about->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
Versioned::set_stage(Versioned::LIVE);
|
Versioned::set_stage(Versioned::LIVE);
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$this->assertFalse($staff->isOrphaned());
|
$this->assertFalse($staff->isOrphaned());
|
||||||
$this->assertTrue($staff->canView($member));
|
$this->assertTrue($staff->canView($member));
|
||||||
|
|
||||||
// Removing staging page should not prevent live page being visible
|
// Removing staging page should not prevent live page being visible
|
||||||
$about->deleteFromStage('Stage');
|
$about->deleteFromStage('Stage');
|
||||||
$staff->deleteFromStage('Stage');
|
$staff->deleteFromStage('Stage');
|
||||||
$staff = $this->objFromFixture('Page', 'staff');
|
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
||||||
$this->assertFalse($staff->isOrphaned());
|
$this->assertFalse($staff->isOrphaned());
|
||||||
$this->assertTrue($staff->canView($member));
|
$this->assertTrue($staff->canView($member));
|
||||||
|
|
||||||
@ -1567,8 +1619,8 @@ class SiteTreeTest extends SapphireTest
|
|||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
$page = $this->objFromFixture('Page', 'home');
|
$page = $this->objFromFixture(SiteTree::class, 'home');
|
||||||
$this->assertTrue($page->canAddChildren());
|
$this->assertTrue($page->canAddChildren());
|
||||||
$this->assertTrue($page->isOnDraft());
|
$this->assertTrue($page->isOnDraft());
|
||||||
$this->assertFalse($page->isPublished());
|
$this->assertFalse($page->isPublished());
|
||||||
@ -1645,23 +1697,24 @@ class SiteTreeTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the controller name for a SiteTree instance can be gathered by appending "Controller" to the SiteTree
|
* Test that the controller name for a Page instance can be gathered by appending "Controller" to the Page
|
||||||
* class name in a PSR-2 compliant manner.
|
* class name in a PSR-2 compliant manner.
|
||||||
*/
|
*/
|
||||||
public function testGetControllerName()
|
public function testGetControllerName()
|
||||||
{
|
{
|
||||||
$class = new Page;
|
$page = new Page();
|
||||||
$this->assertSame('PageController', $class->getControllerName());
|
$this->assertSame(PageController::class, $page->getControllerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that the controller name for a SiteTree instance can be gathered when set directly via config var
|
* Test that the controller name for a SiteTree instance can be gathered when set directly via config var
|
||||||
*/
|
*/
|
||||||
public function testGetControllerNameFromConfig()
|
public function testGetControllerNameFromConfig()
|
||||||
{
|
{
|
||||||
Config::inst()->set(Page::class, 'controller_name', 'This\\Is\\A\\New\\Controller');
|
Config::inst()->set(SiteTree::class, 'controller_name', 'This\\Is\\A\\New\\Controller');
|
||||||
$class = new Page;
|
$page = new SiteTree();
|
||||||
$this->assertSame('This\\Is\\A\\New\\Controller', $class->getControllerName());
|
$this->assertSame('This\\Is\\A\\New\\Controller', $page->getControllerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1677,21 +1730,9 @@ class SiteTreeTest extends SapphireTest
|
|||||||
$this->assertSame(SiteTreeTest_NamespaceMapTestController::class, $namespacedSiteTree->getControllerName());
|
$this->assertSame(SiteTreeTest_NamespaceMapTestController::class, $namespacedSiteTree->getControllerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that underscored class names (legacy) are still supported (deprecation notice is issued though).
|
|
||||||
*/
|
|
||||||
public function testGetControllerNameWithUnderscoresIsSupported()
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
$class = new SiteTreeTest_LegacyControllerName;
|
|
||||||
$this->assertEquals(SiteTreeTest_LegacyControllerName_Controller::class, $class->getControllerName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTreeTitleCache()
|
public function testTreeTitleCache()
|
||||||
{
|
{
|
||||||
$siteTree = SiteTree::create();
|
$siteTree = new SiteTree();
|
||||||
$user = $this->objFromFixture(Member::class, 'allsections');
|
$user = $this->objFromFixture(Member::class, 'allsections');
|
||||||
Security::setCurrentUser($user);
|
Security::setCurrentUser($user);
|
||||||
$pageClass = array_values(SiteTree::page_type_classes())[0];
|
$pageClass = array_values(SiteTree::page_type_classes())[0];
|
||||||
@ -1778,7 +1819,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create new page on DRAFT
|
// Create new page on DRAFT
|
||||||
$page = SiteTree::create();
|
$page = new SiteTree();
|
||||||
$page->Content = $content;
|
$page->Content = $content;
|
||||||
$page->write();
|
$page->write();
|
||||||
|
|
||||||
@ -1794,7 +1835,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testGetCMSActions()
|
public function testGetCMSActions()
|
||||||
{
|
{
|
||||||
// Create new page on DRAFT
|
// Create new page on DRAFT
|
||||||
$page = SiteTree::create();
|
$page = new SiteTree();
|
||||||
$page->Content = md5(rand(0, PHP_INT_MAX));
|
$page->Content = md5(rand(0, PHP_INT_MAX));
|
||||||
$page->write();
|
$page->write();
|
||||||
|
|
||||||
@ -1924,7 +1965,7 @@ class SiteTreeTest extends SapphireTest
|
|||||||
public function testGetCMSActionsWithoutForms()
|
public function testGetCMSActionsWithoutForms()
|
||||||
{
|
{
|
||||||
// Create new page on DRAFT
|
// Create new page on DRAFT
|
||||||
$page = SiteTree::create();
|
$page = new SiteTree();
|
||||||
$page->Content = md5(rand(0, PHP_INT_MAX));
|
$page->Content = md5(rand(0, PHP_INT_MAX));
|
||||||
$page->write();
|
$page->write();
|
||||||
|
|
||||||
@ -2030,20 +2071,10 @@ class SiteTreeTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function testSanitiseExtraMeta(string $extraMeta, string $expected, string $message): void
|
public function testSanitiseExtraMeta(string $extraMeta, string $expected, string $message): void
|
||||||
{
|
{
|
||||||
// If using HTML5Value then the 'somethingdodgy' test won't be converted to valid html
|
|
||||||
// However if using the default HTMLValue, then it will be converted to valid html
|
|
||||||
$isDodgyAndUsingHTML5 = strpos($expected, 'somethingdodgy') !== false &&
|
|
||||||
(HTMLValue::create() instanceof HTML5Value);
|
|
||||||
if ($isDodgyAndUsingHTML5) {
|
|
||||||
$this->expectException(ValidationException::class);
|
|
||||||
$this->expectExceptionMessage('Custom Meta Tags does not contain valid HTML');
|
|
||||||
}
|
|
||||||
$siteTree = new SiteTree();
|
$siteTree = new SiteTree();
|
||||||
$siteTree->ExtraMeta = $extraMeta;
|
$siteTree->ExtraMeta = $extraMeta;
|
||||||
$siteTree->write();
|
$siteTree->write();
|
||||||
if (!$isDodgyAndUsingHTML5) {
|
$this->assertSame($expected, $siteTree->ExtraMeta, $message);
|
||||||
$this->assertSame($expected, $siteTree->ExtraMeta, $message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provideSanitiseExtraMeta(): array
|
public function provideSanitiseExtraMeta(): array
|
||||||
@ -2073,50 +2104,12 @@ class SiteTreeTest extends SapphireTest
|
|||||||
'<link rel="canonical" accesskey="X" onclick="alert(1)" name="x" />',
|
'<link rel="canonical" accesskey="X" onclick="alert(1)" name="x" />',
|
||||||
'<link rel="canonical" name="x">',
|
'<link rel="canonical" name="x">',
|
||||||
'Multiple attributes are removed'
|
'Multiple attributes are removed'
|
||||||
]
|
],
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider provideSanatiseInvalidExtraMeta
|
|
||||||
*/
|
|
||||||
public function testSanatiseInvalidExtraMetaHTML4Value(string $extraMeta, string $expected): void
|
|
||||||
{
|
|
||||||
Injector::inst()->registerService(HTML4Value::create(), HTMLValue::class);
|
|
||||||
$siteTree = new SiteTree();
|
|
||||||
$siteTree->ExtraMeta = $extraMeta;
|
|
||||||
$siteTree->write();
|
|
||||||
$this->assertSame(
|
|
||||||
$expected,
|
|
||||||
$siteTree->ExtraMeta,
|
|
||||||
'Invalid HTML is converted to valid HTML and parsed'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dataProvider provideSanatiseInvalidExtraMeta
|
|
||||||
*/
|
|
||||||
public function testSanatiseInvalidExtraMetaHTML5Value(string $extraMeta): void
|
|
||||||
{
|
|
||||||
// HTML5Value comes from the module silverstripe/html5
|
|
||||||
if (!class_exists(HTML5Value::class)) {
|
|
||||||
$this->markTestSkipped('HTML5Value class does not exist');
|
|
||||||
}
|
|
||||||
Injector::inst()->registerService(HTML5Value::create(), HTMLValue::class);
|
|
||||||
$this->expectException(ValidationException::class);
|
|
||||||
$this->expectExceptionMessage('Custom Meta Tags does not contain valid HTML');
|
|
||||||
$siteTree = new SiteTree();
|
|
||||||
$siteTree->ExtraMeta = $extraMeta;
|
|
||||||
$siteTree->write();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function provideSanatiseInvalidExtraMeta(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
[
|
[
|
||||||
'<link rel="canonical" href="valid" ;;// somethingdodgy < onmouseover=alert(1)',
|
'<link rel="canonical" href="valid" ;;// somethingdodgy <onmouseover=alert(1)>',
|
||||||
'<link rel="canonical" href="valid" somethingdodgy="">'
|
'<link rel="canonical" href="valid" somethingdodgy=""><onmouseover></onmouseover>',
|
||||||
]
|
'Invalid HTML is converted to valid HTML and parsed'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
tests/php/Model/SiteTreeTest.yml
Executable file → Normal file
26
tests/php/Model/SiteTreeTest.yml
Executable file → Normal file
@ -44,7 +44,7 @@ SilverStripe\Security\Member:
|
|||||||
securityadmin:
|
securityadmin:
|
||||||
Groups: =>SilverStripe\Security\Group.securityadmins
|
Groups: =>SilverStripe\Security\Group.securityadmins
|
||||||
|
|
||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
home:
|
home:
|
||||||
Title: Home
|
Title: Home
|
||||||
CanEditType: OnlyTheseUsers
|
CanEditType: OnlyTheseUsers
|
||||||
@ -56,14 +56,14 @@ Page:
|
|||||||
staff:
|
staff:
|
||||||
Title: Staff
|
Title: Staff
|
||||||
URLSegment: my-staff
|
URLSegment: my-staff
|
||||||
Parent: =>Page.about
|
Parent: =>SilverStripe\CMS\Model\SiteTree.about
|
||||||
ceo:
|
ceo:
|
||||||
Title: CEO
|
Title: CEO
|
||||||
Parent: =>Page.staff
|
Parent: =>SilverStripe\CMS\Model\SiteTree.staff
|
||||||
staffduplicate:
|
staffduplicate:
|
||||||
Title: Staff
|
Title: Staff
|
||||||
URLSegment: my-staff
|
URLSegment: my-staff
|
||||||
Parent: =>Page.about
|
Parent: =>SilverStripe\CMS\Model\SiteTree.about
|
||||||
ShowInMenus: 0
|
ShowInMenus: 0
|
||||||
products:
|
products:
|
||||||
Title: Products
|
Title: Products
|
||||||
@ -71,19 +71,19 @@ Page:
|
|||||||
EditorGroups: =>SilverStripe\Security\Group.editors
|
EditorGroups: =>SilverStripe\Security\Group.editors
|
||||||
product1:
|
product1:
|
||||||
Title: 1.1 Test Product
|
Title: 1.1 Test Product
|
||||||
Parent: =>Page.products
|
Parent: =>SilverStripe\CMS\Model\SiteTree.products
|
||||||
CanEditType: Inherit
|
CanEditType: Inherit
|
||||||
product2:
|
product2:
|
||||||
Title: Another Product
|
Title: Another Product
|
||||||
Parent: =>Page.products
|
Parent: =>SilverStripe\CMS\Model\SiteTree.products
|
||||||
CanEditType: Inherit
|
CanEditType: Inherit
|
||||||
product3:
|
product3:
|
||||||
Title: Another Product
|
Title: Another Product
|
||||||
Parent: =>Page.products
|
Parent: =>SilverStripe\CMS\Model\SiteTree.products
|
||||||
CanEditType: Inherit
|
CanEditType: Inherit
|
||||||
product4:
|
product4:
|
||||||
Title: Another Product
|
Title: Another Product
|
||||||
Parent: =>Page.products
|
Parent: =>SilverStripe\CMS\Model\SiteTree.products
|
||||||
CanEditType: OnlyTheseUsers
|
CanEditType: OnlyTheseUsers
|
||||||
EditorGroups: =>SilverStripe\Security\Group.admins
|
EditorGroups: =>SilverStripe\Security\Group.admins
|
||||||
contact:
|
contact:
|
||||||
@ -102,16 +102,16 @@ Page:
|
|||||||
Title: 'Breadcrumbs'
|
Title: 'Breadcrumbs'
|
||||||
breadcrumbs2:
|
breadcrumbs2:
|
||||||
Title: 'Breadcrumbs 2'
|
Title: 'Breadcrumbs 2'
|
||||||
Parent: =>Page.breadcrumbs
|
Parent: =>SilverStripe\CMS\Model\SiteTree.breadcrumbs
|
||||||
breadcrumbs3:
|
breadcrumbs3:
|
||||||
Title: 'Breadcrumbs 3'
|
Title: 'Breadcrumbs 3'
|
||||||
Parent: =>Page.breadcrumbs2
|
Parent: =>SilverStripe\CMS\Model\SiteTree.breadcrumbs2
|
||||||
breadcrumbs4:
|
breadcrumbs4:
|
||||||
Title: 'Breadcrumbs 4'
|
Title: 'Breadcrumbs 4'
|
||||||
Parent: =>Page.breadcrumbs3
|
Parent: =>SilverStripe\CMS\Model\SiteTree.breadcrumbs3
|
||||||
breadcrumbs5:
|
breadcrumbs5:
|
||||||
Title: 'Breadcrumbs 5'
|
Title: 'Breadcrumbs 5'
|
||||||
Parent: =>Page.breadcrumbs4
|
Parent: =>SilverStripe\CMS\Model\SiteTree.breadcrumbs4
|
||||||
|
|
||||||
SilverStripe\CMS\Tests\Model\SiteTreeTest_Conflicted:
|
SilverStripe\CMS\Tests\Model\SiteTreeTest_Conflicted:
|
||||||
parent:
|
parent:
|
||||||
@ -127,4 +127,4 @@ SilverStripe\CMS\Model\RedirectorPage:
|
|||||||
SilverStripe\CMS\Tests\Model\SiteTreeTest_DataObject:
|
SilverStripe\CMS\Tests\Model\SiteTreeTest_DataObject:
|
||||||
relations:
|
relations:
|
||||||
Title: 'Linked DataObject'
|
Title: 'Linked DataObject'
|
||||||
Pages: =>Page.home,=>Page.about,=>Page.staff
|
Pages: =>SilverStripe\CMS\Model\SiteTree.home,=>SilverStripe\CMS\Model\SiteTree.about,=>SilverStripe\CMS\Model\SiteTree.staff
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_AdminDenied extends Page implements TestOnly
|
class SiteTreeTest_AdminDenied extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_AdminDenied';
|
private static $table_name = 'SiteTreeTest_AdminDenied';
|
||||||
|
|
||||||
|
@ -3,18 +3,18 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_ClassA extends Page implements TestOnly
|
class SiteTreeTest_ClassA extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_ClassA';
|
private static $table_name = 'SiteTreeTest_ClassA';
|
||||||
|
|
||||||
private static $need_permission = [
|
private static $need_permission = [
|
||||||
'ADMIN',
|
'ADMIN',
|
||||||
'CMS_ACCESS_CMSMain'
|
'CMS_ACCESS_CMSMain',
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $allowed_children = [
|
private static $allowed_children = [
|
||||||
SiteTreeTest_ClassB::class
|
SiteTreeTest_ClassB::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_ClassB extends Page implements TestOnly
|
class SiteTreeTest_ClassB extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_ClassB';
|
private static $table_name = 'SiteTreeTest_ClassB';
|
||||||
|
|
||||||
// Also allowed subclasses
|
// Also allowed subclasses
|
||||||
private static $allowed_children = [
|
private static $allowed_children = [
|
||||||
SiteTreeTest_ClassC::class
|
SiteTreeTest_ClassC::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_ClassC extends Page implements TestOnly
|
class SiteTreeTest_ClassC extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_ClassC';
|
private static $table_name = 'SiteTreeTest_ClassC';
|
||||||
|
|
||||||
|
@ -10,6 +10,6 @@ class SiteTreeTest_ClassCext extends SiteTreeTest_ClassC implements TestOnly
|
|||||||
|
|
||||||
// Override SiteTreeTest_ClassC definitions
|
// Override SiteTreeTest_ClassC definitions
|
||||||
private static $allowed_children = [
|
private static $allowed_children = [
|
||||||
SiteTreeTest_ClassB::class
|
SiteTreeTest_ClassB::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_ClassD extends Page implements TestOnly
|
class SiteTreeTest_ClassD extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_ClassD';
|
private static $table_name = 'SiteTreeTest_ClassD';
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@ namespace SilverStripe\CMS\Tests\Model;
|
|||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\HiddenClass;
|
use SilverStripe\ORM\HiddenClass;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_ClassE extends Page implements TestOnly, HiddenClass
|
class SiteTreeTest_ClassE extends SiteTree implements TestOnly, HiddenClass
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_ClassE';
|
private static $table_name = 'SiteTreeTest_ClassE';
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_Conflicted extends Page implements TestOnly
|
class SiteTreeTest_Conflicted extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_Conflicted';
|
private static $table_name = 'SiteTreeTest_Conflicted';
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use PageController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
|
|
||||||
class SiteTreeTest_ConflictedController extends PageController implements TestOnly
|
class SiteTreeTest_ConflictedController extends ContentController implements TestOnly
|
||||||
{
|
{
|
||||||
private static $allowed_actions = [
|
private static $allowed_actions = [
|
||||||
'conflicted-action'
|
'conflicted-action',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function hasActionTemplate($template)
|
public function hasActionTemplate($template)
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An empty SiteTree instance with a controller to test that legacy controller names can still be loaded
|
* An empty SiteTree instance with a controller to test that legacy controller names can still be loaded
|
||||||
*/
|
*/
|
||||||
class SiteTreeTest_LegacyControllerName extends Page implements TestOnly
|
class SiteTreeTest_LegacyControllerName extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_LegacyControllerName';
|
private static $table_name = 'SiteTreeTest_LegacyControllerName';
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use PageController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
|
|
||||||
class SiteTreeTest_LegacyControllerName_Controller extends PageController implements TestOnly
|
class SiteTreeTest_LegacyControllerName_Controller extends ContentController implements TestOnly
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_NotRoot extends Page implements TestOnly
|
class SiteTreeTest_NotRoot extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_NotRoot';
|
private static $table_name = 'SiteTreeTest_NotRoot';
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class SiteTreeTest_PageNode extends Page implements TestOnly
|
class SiteTreeTest_PageNode extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'SiteTreeTest_PageNode';
|
private static $table_name = 'SiteTreeTest_PageNode';
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use PageController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
|
|
||||||
class SiteTreeTest_PageNodeController extends PageController implements TestOnly
|
class SiteTreeTest_PageNodeController extends ContentController implements TestOnly
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\CMS\Controllers\ModelAsController;
|
use SilverStripe\CMS\Controllers\ModelAsController;
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
@ -43,8 +42,8 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
|
|
||||||
protected static $required_extensions = [
|
protected static $required_extensions = [
|
||||||
SiteTree::class => [
|
SiteTree::class => [
|
||||||
VirtualPageTest_PageExtension::class
|
VirtualPageTest_PageExtension::class,
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
@ -63,8 +62,8 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Ensure all pages are published
|
// Ensure all pages are published
|
||||||
/** @var Page $page */
|
/** @var SiteTree $page */
|
||||||
foreach (Page::get() as $page) {
|
foreach (SiteTree::get() as $page) {
|
||||||
$page->publishSingle();
|
$page->publishSingle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,8 +74,8 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
*/
|
*/
|
||||||
public function testEditingSourcePageUpdatesVirtualPages()
|
public function testEditingSourcePageUpdatesVirtualPages()
|
||||||
{
|
{
|
||||||
/** @var Page $master */
|
/** @var SiteTree $master */
|
||||||
$master = $this->objFromFixture('Page', 'master');
|
$master = $this->objFromFixture(SiteTree::class, 'master');
|
||||||
$master->Title = "New title";
|
$master->Title = "New title";
|
||||||
$master->MenuTitle = "New menutitle";
|
$master->MenuTitle = "New menutitle";
|
||||||
$master->Content = "<p>New content</p>";
|
$master->Content = "<p>New content</p>";
|
||||||
@ -97,7 +96,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
public function testMetaTags()
|
public function testMetaTags()
|
||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
$master = $this->objFromFixture('Page', 'master');
|
$master = $this->objFromFixture(SiteTree::class, 'master');
|
||||||
$vp1 = $this->objFromFixture(VirtualPage::class, 'vp1');
|
$vp1 = $this->objFromFixture(VirtualPage::class, 'vp1');
|
||||||
|
|
||||||
// Test with title
|
// Test with title
|
||||||
@ -118,8 +117,8 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
{
|
{
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
/** @var Page $master */
|
/** @var SiteTree $master */
|
||||||
$master = $this->objFromFixture('Page', 'master');
|
$master = $this->objFromFixture(SiteTree::class, 'master');
|
||||||
$master->publishRecursive();
|
$master->publishRecursive();
|
||||||
|
|
||||||
$master->Title = "New title";
|
$master->Title = "New title";
|
||||||
@ -160,13 +159,13 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
$vp = new VirtualPage();
|
$vp = new VirtualPage();
|
||||||
$vp->write();
|
$vp->write();
|
||||||
|
|
||||||
$vp->CopyContentFromID = $this->idFromFixture('Page', 'master');
|
$vp->CopyContentFromID = $this->idFromFixture(SiteTree::class, 'master');
|
||||||
$vp->write();
|
$vp->write();
|
||||||
|
|
||||||
$this->assertEquals("My Page", $vp->Title);
|
$this->assertEquals("My Page", $vp->Title);
|
||||||
$this->assertEquals("My Page Nav", $vp->MenuTitle);
|
$this->assertEquals("My Page Nav", $vp->MenuTitle);
|
||||||
|
|
||||||
$vp->CopyContentFromID = $this->idFromFixture('Page', 'master2');
|
$vp->CopyContentFromID = $this->idFromFixture(SiteTree::class, 'master2');
|
||||||
$vp->write();
|
$vp->write();
|
||||||
|
|
||||||
$this->assertEquals("My Other Page", $vp->Title);
|
$this->assertEquals("My Other Page", $vp->Title);
|
||||||
@ -180,7 +179,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
*/
|
*/
|
||||||
public function testPublishingAVirtualPageCopiedPublishedContentNotDraftContent()
|
public function testPublishingAVirtualPageCopiedPublishedContentNotDraftContent()
|
||||||
{
|
{
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Content = "published content";
|
$p->Content = "published content";
|
||||||
$p->write();
|
$p->write();
|
||||||
$p->publishRecursive();
|
$p->publishRecursive();
|
||||||
@ -220,7 +219,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
public function testCantPublishVirtualPagesBeforeTheirSource()
|
public function testCantPublishVirtualPagesBeforeTheirSource()
|
||||||
{
|
{
|
||||||
// An unpublished source page
|
// An unpublished source page
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Content = "test content";
|
$p->Content = "test content";
|
||||||
$p->write();
|
$p->write();
|
||||||
|
|
||||||
@ -241,7 +240,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testCanEdit()
|
public function testCanEdit()
|
||||||
{
|
{
|
||||||
$parentPage = $this->objFromFixture('Page', 'master3');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'master3');
|
||||||
$virtualPage = $this->objFromFixture(VirtualPage::class, 'vp3');
|
$virtualPage = $this->objFromFixture(VirtualPage::class, 'vp3');
|
||||||
$bob = $this->objFromFixture(Member::class, 'bob');
|
$bob = $this->objFromFixture(Member::class, 'bob');
|
||||||
$andrew = $this->objFromFixture(Member::class, 'andrew');
|
$andrew = $this->objFromFixture(Member::class, 'andrew');
|
||||||
@ -259,8 +258,8 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testCanView()
|
public function testCanView()
|
||||||
{
|
{
|
||||||
/** @var Page $parentPage */
|
/** @var SiteTree $parentPage */
|
||||||
$parentPage = $this->objFromFixture('Page', 'master3');
|
$parentPage = $this->objFromFixture(SiteTree::class, 'master3');
|
||||||
$parentPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
$parentPage->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
|
||||||
|
|
||||||
/** @var VirtualPage $virtualPage */
|
/** @var VirtualPage $virtualPage */
|
||||||
@ -283,7 +282,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
public function testVirtualPagesArentInappropriatelyPublished()
|
public function testVirtualPagesArentInappropriatelyPublished()
|
||||||
{
|
{
|
||||||
// Fixture
|
// Fixture
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Content = "test content";
|
$p->Content = "test content";
|
||||||
$p->write();
|
$p->write();
|
||||||
$vp = new VirtualPage();
|
$vp = new VirtualPage();
|
||||||
@ -332,7 +331,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
public function testUnpublishingSourcePageOfAVirtualPageAlsoUnpublishesVirtualPage()
|
public function testUnpublishingSourcePageOfAVirtualPageAlsoUnpublishesVirtualPage()
|
||||||
{
|
{
|
||||||
// Create page and virutal page
|
// Create page and virutal page
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Title = "source";
|
$p->Title = "source";
|
||||||
$p->write();
|
$p->write();
|
||||||
$this->assertTrue($p->publishRecursive());
|
$this->assertTrue($p->publishRecursive());
|
||||||
@ -364,7 +363,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
public function testDeletingFromLiveSourcePageOfAVirtualPageAlsoUnpublishesVirtualPage()
|
public function testDeletingFromLiveSourcePageOfAVirtualPageAlsoUnpublishesVirtualPage()
|
||||||
{
|
{
|
||||||
// Create page and virutal page
|
// Create page and virutal page
|
||||||
$p = new Page();
|
$p = new SiteTree();
|
||||||
$p->Title = "source";
|
$p->Title = "source";
|
||||||
$p->write();
|
$p->write();
|
||||||
$this->assertTrue($p->publishRecursive());
|
$this->assertTrue($p->publishRecursive());
|
||||||
@ -384,7 +383,7 @@ class VirtualPageTest extends FunctionalTest
|
|||||||
->byID($pID);
|
->byID($pID);
|
||||||
$this->assertNull($vpDraft);
|
$this->assertNull($vpDraft);
|
||||||
// Delete the source page form live, confirm that the virtual page has also been unpublished
|
// Delete the source page form live, confirm that the virtual page has also been unpublished
|
||||||
/** @var Page $pLive */
|
/** @var SiteTree $pLive */
|
||||||
$pLive = Versioned::get_by_stage(SiteTree::class, Versioned::LIVE)
|
$pLive = Versioned::get_by_stage(SiteTree::class, Versioned::LIVE)
|
||||||
->byID($pID);
|
->byID($pID);
|
||||||
$this->assertTrue($pLive->doUnpublish());
|
$this->assertTrue($pLive->doUnpublish());
|
||||||
|
@ -31,7 +31,7 @@ SilverStripe\Security\Member:
|
|||||||
alice:
|
alice:
|
||||||
Email: alice@alice.com
|
Email: alice@alice.com
|
||||||
Groups: =>SilverStripe\Security\Group.alicegroup
|
Groups: =>SilverStripe\Security\Group.alicegroup
|
||||||
Page:
|
SilverStripe\CMS\Model\SiteTree:
|
||||||
master:
|
master:
|
||||||
Title: My Page
|
Title: My Page
|
||||||
MenuTitle: My Page Nav
|
MenuTitle: My Page Nav
|
||||||
@ -52,15 +52,15 @@ SilverStripe\CMS\Tests\Model\VirtualPageTest_ClassA:
|
|||||||
SilverStripe\CMS\Model\VirtualPage:
|
SilverStripe\CMS\Model\VirtualPage:
|
||||||
vp1:
|
vp1:
|
||||||
Title: vp1
|
Title: vp1
|
||||||
CopyContentFrom: =>Page.master
|
CopyContentFrom: =>SilverStripe\CMS\Model\SiteTree.master
|
||||||
Parent: =>Page.holder
|
Parent: =>SilverStripe\CMS\Model\SiteTree.holder
|
||||||
vp2:
|
vp2:
|
||||||
Title: vp2
|
Title: vp2
|
||||||
CopyContentFrom: =>Page.master
|
CopyContentFrom: =>SilverStripe\CMS\Model\SiteTree.master
|
||||||
Parent: =>Page.holder
|
Parent: =>SilverStripe\CMS\Model\SiteTree.holder
|
||||||
vp3:
|
vp3:
|
||||||
CopyContentFrom: =>Page.master3
|
CopyContentFrom: =>SilverStripe\CMS\Model\SiteTree.master3
|
||||||
Parent: =>Page.holder
|
Parent: =>SilverStripe\CMS\Model\SiteTree.holder
|
||||||
CanEditType: OnlyTheseUsers
|
CanEditType: OnlyTheseUsers
|
||||||
CanViewType: OnlyTheseUsers
|
CanViewType: OnlyTheseUsers
|
||||||
EditorGroups: =>SilverStripe\Security\Group.andrewgroup
|
EditorGroups: =>SilverStripe\Security\Group.andrewgroup
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class VirtualPageTest_ClassA extends Page implements TestOnly
|
class VirtualPageTest_ClassA extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'VirtualPageTest_ClassA';
|
private static $table_name = 'VirtualPageTest_ClassA';
|
||||||
|
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use PageController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
|
|
||||||
class VirtualPageTest_ClassAController extends PageController implements TestOnly
|
class VirtualPageTest_ClassAController extends ContentController implements TestOnly
|
||||||
{
|
{
|
||||||
private static $allowed_actions = [
|
private static $allowed_actions = [
|
||||||
'testaction'
|
'testaction',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function testMethod()
|
public function testMethod()
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class VirtualPageTest_ClassB extends Page implements TestOnly
|
class VirtualPageTest_ClassB extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'VirtualPageTest_ClassB';
|
private static $table_name = 'VirtualPageTest_ClassB';
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class VirtualPageTest_ClassC extends Page implements TestOnly
|
class VirtualPageTest_ClassC extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'VirtualPageTest_ClassC';
|
private static $table_name = 'VirtualPageTest_ClassC';
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
namespace SilverStripe\CMS\Tests\Model;
|
namespace SilverStripe\CMS\Tests\Model;
|
||||||
|
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class VirtualPageTest_NotRoot extends Page implements TestOnly
|
class VirtualPageTest_NotRoot extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'VirtualPageTest_NotRoot';
|
private static $table_name = 'VirtualPageTest_NotRoot';
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ class VirtualPageTest_PageExtension extends DataExtension implements TestOnly
|
|||||||
{
|
{
|
||||||
private static $db = [
|
private static $db = [
|
||||||
// These fields are just on an extension to simulate shared properties between Page and VirtualPage.
|
// These fields are just on an extension to simulate shared properties between Page and VirtualPage.
|
||||||
// Not possible through direct $db definitions due to VirtualPage inheriting from Page, and Page being defined elsewhere.
|
// Not possible through direct $db definitions due to VirtualPage inheriting from Page,
|
||||||
|
// and Page being defined elsewhere.
|
||||||
'MySharedVirtualField' => 'Text',
|
'MySharedVirtualField' => 'Text',
|
||||||
'MySharedNonVirtualField' => 'Text',
|
'MySharedNonVirtualField' => 'Text',
|
||||||
];
|
];
|
||||||
|
@ -4,9 +4,9 @@ namespace SilverStripe\CMS\Tests\Model;
|
|||||||
|
|
||||||
use SilverStripe\CMS\Model\VirtualPage;
|
use SilverStripe\CMS\Model\VirtualPage;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use Page;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
|
||||||
class VirtualPageTest_PageWithAllowedChildren extends Page implements TestOnly
|
class VirtualPageTest_PageWithAllowedChildren extends SiteTree implements TestOnly
|
||||||
{
|
{
|
||||||
private static $table_name = 'VirtualPageTest_PageWithAllowedChildren';
|
private static $table_name = 'VirtualPageTest_PageWithAllowedChildren';
|
||||||
|
|
||||||
|
@ -2,24 +2,22 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Reports;
|
namespace SilverStripe\CMS\Tests\Reports;
|
||||||
|
|
||||||
|
use SilverStripe\Assets\File;
|
||||||
|
use SilverStripe\CMS\Model\RedirectorPage;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
|
use SilverStripe\CMS\Model\VirtualPage;
|
||||||
|
use SilverStripe\CMS\Reports\BrokenFilesReport;
|
||||||
|
use SilverStripe\CMS\Reports\BrokenLinksReport;
|
||||||
|
use SilverStripe\CMS\Reports\BrokenRedirectorPagesReport;
|
||||||
|
use SilverStripe\CMS\Reports\BrokenVirtualPagesReport;
|
||||||
|
use SilverStripe\CMS\Reports\RecentlyEditedReport;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||||
use SilverStripe\CMS\Reports\RecentlyEditedReport;
|
|
||||||
use SilverStripe\CMS\Reports\BrokenLinksReport;
|
|
||||||
use SilverStripe\CMS\Reports\BrokenFilesReport;
|
|
||||||
use SilverStripe\CMS\Model\VirtualPage;
|
|
||||||
use SilverStripe\CMS\Reports\BrokenVirtualPagesReport;
|
|
||||||
use SilverStripe\CMS\Model\RedirectorPage;
|
|
||||||
use SilverStripe\CMS\Reports\BrokenRedirectorPagesReport;
|
|
||||||
use SilverStripe\Reports\Report;
|
use SilverStripe\Reports\Report;
|
||||||
use SilverStripe\Assets\File;
|
|
||||||
use SilverStripe\Dev\SapphireTest;
|
|
||||||
use Page;
|
|
||||||
|
|
||||||
class CmsReportsTest extends SapphireTest
|
class CmsReportsTest extends SapphireTest
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $fixture_file = 'CmsReportsTest.yml';
|
protected static $fixture_file = 'CmsReportsTest.yml';
|
||||||
|
|
||||||
private static $daysAgo = 14;
|
private static $daysAgo = 14;
|
||||||
@ -29,14 +27,19 @@ class CmsReportsTest extends SapphireTest
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
// set the dates by hand: impossible to set via yml
|
// set the dates by hand: impossible to set via yml
|
||||||
$afterThreshold = strtotime('-'.(self::$daysAgo-1).' days', strtotime('31-06-2009 00:00:00'));
|
$afterThreshold = strtotime('-' . (self::$daysAgo - 1) . ' days', strtotime('31-06-2009 00:00:00'));
|
||||||
$beforeThreshold = strtotime('-'.(self::$daysAgo+1).' days', strtotime('31-06-2009 00:00:00'));
|
$beforeThreshold = strtotime('-' . (self::$daysAgo + 1) . ' days', strtotime('31-06-2009 00:00:00'));
|
||||||
|
|
||||||
$after = $this->objFromFixture(SiteTree::class, 'after');
|
$after = $this->objFromFixture(SiteTree::class, 'after');
|
||||||
$before = $this->objFromFixture(SiteTree::class, 'before');
|
$before = $this->objFromFixture(SiteTree::class, 'before');
|
||||||
|
DB::query(
|
||||||
DB::query("UPDATE \"SiteTree\" SET \"Created\"='2009-01-01 00:00:00', \"LastEdited\"='".date('Y-m-d H:i:s', $afterThreshold)."' WHERE \"ID\"='".$after->ID."'");
|
"UPDATE \"SiteTree\" SET \"Created\"='2009-01-01 00:00:00', \"LastEdited\"='" .
|
||||||
DB::query("UPDATE \"SiteTree\" SET \"Created\"='2009-01-01 00:00:00', \"LastEdited\"='".date('Y-m-d H:i:s', $beforeThreshold)."' WHERE \"ID\"='".$before->ID."'");
|
date('Y-m-d H:i:s', $afterThreshold) . "' WHERE \"ID\"='" . $after->ID . "'"
|
||||||
|
);
|
||||||
|
DB::query(
|
||||||
|
"UPDATE \"SiteTree\" SET \"Created\"='2009-01-01 00:00:00', \"LastEdited\"='" .
|
||||||
|
date('Y-m-d H:i:s', $beforeThreshold) . "' WHERE \"ID\"='" . $before->ID . "'"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,13 +55,27 @@ class CmsReportsTest extends SapphireTest
|
|||||||
|
|
||||||
// ASSERT that the "draft" report is returning the correct results.
|
// ASSERT that the "draft" report is returning the correct results.
|
||||||
$parameters = ['CheckSite' => 'Draft'];
|
$parameters = ['CheckSite' => 'Draft'];
|
||||||
$results = count($report->sourceRecords($parameters, null, null) ?? []) > 0;
|
$results = count($report->sourceRecords($parameters, null, null)) > 0;
|
||||||
$isDraftBroken ? $this->assertTrue($results, "{$class} has NOT returned the correct DRAFT results, as NO pages were found.") : $this->assertFalse($results, "{$class} has NOT returned the correct DRAFT results, as pages were found.");
|
$isDraftBroken
|
||||||
|
? $this->assertTrue(
|
||||||
|
$results,
|
||||||
|
"{$class} has NOT returned the correct DRAFT results, as NO pages were found."
|
||||||
|
) : $this->assertFalse(
|
||||||
|
$results,
|
||||||
|
"{$class} has NOT returned the correct DRAFT results, as pages were found."
|
||||||
|
);
|
||||||
|
|
||||||
// ASSERT that the "published" report is returning the correct results.
|
// ASSERT that the "published" report is returning the correct results.
|
||||||
$parameters = ['CheckSite' => 'Published', 'OnLive' => 1];
|
$parameters = ['CheckSite' => 'Published', 'OnLive' => 1];
|
||||||
$results = count($report->sourceRecords($parameters, null, null) ?? []) > 0;
|
$results = count($report->sourceRecords($parameters, null, null) ?? []) > 0;
|
||||||
$isPublishedBroken ? $this->assertTrue($results, "{$class} has NOT returned the correct PUBLISHED results, as NO pages were found.") : $this->assertFalse($results, "{$class} has NOT returned the correct PUBLISHED results, as pages were found.");
|
$isPublishedBroken
|
||||||
|
? $this->assertTrue(
|
||||||
|
$results,
|
||||||
|
"{$class} has NOT returned the correct PUBLISHED results, as NO pages were found."
|
||||||
|
) : $this->assertFalse(
|
||||||
|
$results,
|
||||||
|
"{$class} has NOT returned the correct PUBLISHED results, as pages were found."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRecentlyEdited()
|
public function testRecentlyEdited()
|
||||||
@ -81,18 +98,14 @@ class CmsReportsTest extends SapphireTest
|
|||||||
/**
|
/**
|
||||||
* Test the broken links side report.
|
* Test the broken links side report.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function testBrokenLinks()
|
public function testBrokenLinks()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Create a "draft" page with a broken link.
|
// Create a "draft" page with a broken link.
|
||||||
|
$page = new SiteTree();
|
||||||
$page = Page::create();
|
|
||||||
$page->Content = "<a href='[sitetree_link,id=987654321]'>This</a> is a broken link.";
|
$page->Content = "<a href='[sitetree_link,id=987654321]'>This</a> is a broken link.";
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// Retrieve the broken links side report.
|
// Retrieve the broken links side report.
|
||||||
|
|
||||||
$reports = Report::get_reports();
|
$reports = Report::get_reports();
|
||||||
$brokenLinksReport = null;
|
$brokenLinksReport = null;
|
||||||
foreach ($reports as $report) {
|
foreach ($reports as $report) {
|
||||||
@ -109,12 +122,11 @@ class CmsReportsTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken link, as the page has not been "published" yet.
|
// ASSERT that the "published" report has NOT detected the page having a broken link,
|
||||||
|
// as the page has not been "published" yet.
|
||||||
$this->isReportBroken($brokenLinksReport, true, false);
|
$this->isReportBroken($brokenLinksReport, true, false);
|
||||||
|
|
||||||
// Make sure the page is now "published".
|
// Make sure the page is now "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
@ -123,17 +135,15 @@ class CmsReportsTest extends SapphireTest
|
|||||||
$this->isReportBroken($brokenLinksReport, true, true);
|
$this->isReportBroken($brokenLinksReport, true, true);
|
||||||
|
|
||||||
// Correct the "draft" broken link.
|
// Correct the "draft" broken link.
|
||||||
|
|
||||||
$page->Content = str_replace('987654321', $page->ID ?? '', $page->Content ?? '');
|
$page->Content = str_replace('987654321', $page->ID ?? '', $page->Content ?? '');
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has detected the page having a broken link, as the previous content remains "published".
|
// ASSERT that the "published" report has detected the page having a broken link,
|
||||||
|
// as the previous content remains "published".
|
||||||
$this->isReportBroken($brokenLinksReport, false, true);
|
$this->isReportBroken($brokenLinksReport, false, true);
|
||||||
|
|
||||||
// Make sure the change has now been "published".
|
// Make sure the change has now been "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
@ -145,18 +155,14 @@ class CmsReportsTest extends SapphireTest
|
|||||||
/**
|
/**
|
||||||
* Test the broken files side report.
|
* Test the broken files side report.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function testBrokenFiles()
|
public function testBrokenFiles()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Create a "draft" page with a broken file.
|
// Create a "draft" page with a broken file.
|
||||||
|
$page = new SiteTree();
|
||||||
$page = Page::create();
|
|
||||||
$page->Content = "<a href='[file_link,id=987654321]'>This</a> is a broken file.";
|
$page->Content = "<a href='[file_link,id=987654321]'>This</a> is a broken file.";
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// Retrieve the broken files side report.
|
// Retrieve the broken files side report.
|
||||||
|
|
||||||
$reports = Report::get_reports();
|
$reports = Report::get_reports();
|
||||||
$brokenFilesReport = null;
|
$brokenFilesReport = null;
|
||||||
foreach ($reports as $report) {
|
foreach ($reports as $report) {
|
||||||
@ -173,21 +179,18 @@ class CmsReportsTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken file.
|
// ASSERT that the "draft" report has detected the page having a broken file.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken file, as the page has not been "published" yet.
|
// ASSERT that the "published" report has NOT detected the page having a broken file,
|
||||||
|
// as the page has not been "published" yet.
|
||||||
$this->isReportBroken($brokenFilesReport, true, false);
|
$this->isReportBroken($brokenFilesReport, true, false);
|
||||||
|
|
||||||
// Make sure the page is now "published".
|
// Make sure the page is now "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken file.
|
// ASSERT that the "draft" report has detected the page having a broken file.
|
||||||
// ASSERT that the "published" report has detected the page having a broken file.
|
// ASSERT that the "published" report has detected the page having a broken file.
|
||||||
|
|
||||||
$this->isReportBroken($brokenFilesReport, true, true);
|
$this->isReportBroken($brokenFilesReport, true, true);
|
||||||
|
|
||||||
// Correct the "draft" broken file.
|
// Correct the "draft" broken file.
|
||||||
|
|
||||||
$file = File::create();
|
$file = File::create();
|
||||||
$file->Filename = 'name.pdf';
|
$file->Filename = 'name.pdf';
|
||||||
$file->write();
|
$file->write();
|
||||||
@ -195,17 +198,15 @@ class CmsReportsTest extends SapphireTest
|
|||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken file.
|
// ASSERT that the "draft" report has NOT detected the page having a broken file.
|
||||||
// ASSERT that the "published" report has detected the page having a broken file, as the previous content remains "published".
|
// ASSERT that the "published" report has detected the page having a broken file,
|
||||||
|
// as the previous content remains "published".
|
||||||
$this->isReportBroken($brokenFilesReport, false, true);
|
$this->isReportBroken($brokenFilesReport, false, true);
|
||||||
|
|
||||||
// Make sure the change has now been "published".
|
// Make sure the change has now been "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken file.
|
// ASSERT that the "draft" report has NOT detected the page having a broken file.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken file.
|
// ASSERT that the "published" report has NOT detected the page having a broken file.
|
||||||
|
|
||||||
$this->isReportBroken($brokenFilesReport, false, false);
|
$this->isReportBroken($brokenFilesReport, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,15 +216,12 @@ class CmsReportsTest extends SapphireTest
|
|||||||
|
|
||||||
public function testBrokenVirtualPages()
|
public function testBrokenVirtualPages()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Create a "draft" virtual page with a broken link.
|
// Create a "draft" virtual page with a broken link.
|
||||||
|
|
||||||
$page = VirtualPage::create();
|
$page = VirtualPage::create();
|
||||||
$page->CopyContentFromID = 987654321;
|
$page->CopyContentFromID = 987654321;
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// Retrieve the broken virtual pages side report.
|
// Retrieve the broken virtual pages side report.
|
||||||
|
|
||||||
$reports = Report::get_reports();
|
$reports = Report::get_reports();
|
||||||
$brokenVirtualPagesReport = null;
|
$brokenVirtualPagesReport = null;
|
||||||
foreach ($reports as $report) {
|
foreach ($reports as $report) {
|
||||||
@ -240,22 +238,19 @@ class CmsReportsTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken link, as the page has not been "published" yet.
|
// ASSERT that the "published" report has NOT detected the page having a broken link,
|
||||||
|
// as the page has not been "published" yet.
|
||||||
$this->isReportBroken($brokenVirtualPagesReport, true, false);
|
$this->isReportBroken($brokenVirtualPagesReport, true, false);
|
||||||
|
|
||||||
// Make sure the page is now "published".
|
// Make sure the page is now "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has detected the page having a broken link.
|
// ASSERT that the "published" report has detected the page having a broken link.
|
||||||
|
|
||||||
$this->isReportBroken($brokenVirtualPagesReport, true, true);
|
$this->isReportBroken($brokenVirtualPagesReport, true, true);
|
||||||
|
|
||||||
// Correct the "draft" broken link.
|
// Correct the "draft" broken link.
|
||||||
|
$contentPage = new SiteTree();
|
||||||
$contentPage = Page::create();
|
|
||||||
$contentPage->Content = 'This is some content.';
|
$contentPage->Content = 'This is some content.';
|
||||||
$contentPage->writeToStage('Stage');
|
$contentPage->writeToStage('Stage');
|
||||||
$contentPage->writeToStage('Live');
|
$contentPage->writeToStage('Live');
|
||||||
@ -263,36 +258,30 @@ class CmsReportsTest extends SapphireTest
|
|||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has detected the page having a broken link, as the previous content remains "published".
|
// ASSERT that the "published" report has detected the page having a broken link,
|
||||||
|
// as the previous content remains "published".
|
||||||
$this->isReportBroken($brokenVirtualPagesReport, false, true);
|
$this->isReportBroken($brokenVirtualPagesReport, false, true);
|
||||||
|
|
||||||
// Make sure the change has now been "published".
|
// Make sure the change has now been "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken link.
|
// ASSERT that the "published" report has NOT detected the page having a broken link.
|
||||||
|
|
||||||
$this->isReportBroken($brokenVirtualPagesReport, false, false);
|
$this->isReportBroken($brokenVirtualPagesReport, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the broken redirector pages side report.
|
* Test the broken redirector pages side report.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function testBrokenRedirectorPages()
|
public function testBrokenRedirectorPages()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Create a "draft" redirector page with a broken link.
|
// Create a "draft" redirector page with a broken link.
|
||||||
|
|
||||||
$page = RedirectorPage::create();
|
$page = RedirectorPage::create();
|
||||||
$page->RedirectionType = 'Internal';
|
$page->RedirectionType = 'Internal';
|
||||||
$page->LinkToID = 987654321;
|
$page->LinkToID = 987654321;
|
||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// Retrieve the broken redirector pages side report.
|
// Retrieve the broken redirector pages side report.
|
||||||
|
|
||||||
$reports = Report::get_reports();
|
$reports = Report::get_reports();
|
||||||
$brokenRedirectorPagesReport = null;
|
$brokenRedirectorPagesReport = null;
|
||||||
foreach ($reports as $report) {
|
foreach ($reports as $report) {
|
||||||
@ -309,22 +298,19 @@ class CmsReportsTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken link, as the page has not been "published" yet.
|
// ASSERT that the "published" report has NOT detected the page having a broken link,
|
||||||
|
// as the page has not been "published" yet.
|
||||||
$this->isReportBroken($brokenRedirectorPagesReport, true, false);
|
$this->isReportBroken($brokenRedirectorPagesReport, true, false);
|
||||||
|
|
||||||
// Make sure the page is now "published".
|
// Make sure the page is now "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has detected the page having a broken link.
|
// ASSERT that the "draft" report has detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has detected the page having a broken link.
|
// ASSERT that the "published" report has detected the page having a broken link.
|
||||||
|
|
||||||
$this->isReportBroken($brokenRedirectorPagesReport, true, true);
|
$this->isReportBroken($brokenRedirectorPagesReport, true, true);
|
||||||
|
|
||||||
// Correct the "draft" broken link.
|
// Correct the "draft" broken link.
|
||||||
|
$contentPage = new SiteTree();
|
||||||
$contentPage = Page::create();
|
|
||||||
$contentPage->Content = 'This is some content.';
|
$contentPage->Content = 'This is some content.';
|
||||||
$contentPage->writeToStage('Stage');
|
$contentPage->writeToStage('Stage');
|
||||||
$contentPage->writeToStage('Live');
|
$contentPage->writeToStage('Live');
|
||||||
@ -332,17 +318,15 @@ class CmsReportsTest extends SapphireTest
|
|||||||
$page->writeToStage('Stage');
|
$page->writeToStage('Stage');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has detected the page having a broken link, as the previous content remains "published".
|
// ASSERT that the "published" report has detected the page having a broken link,
|
||||||
|
// as the previous content remains "published".
|
||||||
$this->isReportBroken($brokenRedirectorPagesReport, false, true);
|
$this->isReportBroken($brokenRedirectorPagesReport, false, true);
|
||||||
|
|
||||||
// Make sure the change has now been "published".
|
// Make sure the change has now been "published".
|
||||||
|
|
||||||
$page->writeToStage('Live');
|
$page->writeToStage('Live');
|
||||||
|
|
||||||
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
// ASSERT that the "draft" report has NOT detected the page having a broken link.
|
||||||
// ASSERT that the "published" report has NOT detected the page having a broken link.
|
// ASSERT that the "published" report has NOT detected the page having a broken link.
|
||||||
|
|
||||||
$this->isReportBroken($brokenRedirectorPagesReport, false, false);
|
$this->isReportBroken($brokenRedirectorPagesReport, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class CMSMainSearchFormTest extends FunctionalTest
|
|||||||
'q' => [
|
'q' => [
|
||||||
'Term' => 'Page 10',
|
'Term' => 'Page 10',
|
||||||
'FilterClass' => CMSSiteTreeFilter_Search::class,
|
'FilterClass' => CMSSiteTreeFilter_Search::class,
|
||||||
]
|
],
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Search;
|
namespace SilverStripe\CMS\Tests\Search;
|
||||||
|
|
||||||
use Page;
|
|
||||||
use SilverStripe\Assets\File;
|
use SilverStripe\Assets\File;
|
||||||
use SilverStripe\CMS\Controllers\ContentController;
|
use SilverStripe\CMS\Controllers\ContentController;
|
||||||
use SilverStripe\CMS\Controllers\ModelAsController;
|
use SilverStripe\CMS\Controllers\ModelAsController;
|
||||||
@ -29,7 +28,6 @@ use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
|
|||||||
*/
|
*/
|
||||||
class ZZZSearchFormTest extends FunctionalTest
|
class ZZZSearchFormTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
|
|
||||||
protected static $fixture_file = 'ZZZSearchFormTest.yml';
|
protected static $fixture_file = 'ZZZSearchFormTest.yml';
|
||||||
|
|
||||||
protected static $illegal_extensions = [
|
protected static $illegal_extensions = [
|
||||||
@ -97,9 +95,6 @@ class ZZZSearchFormTest extends FunctionalTest
|
|||||||
return $supports;
|
return $supports;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @skipUpgrade
|
|
||||||
*/
|
|
||||||
public function testSearchFormTemplateCanBeChanged()
|
public function testSearchFormTemplateCanBeChanged()
|
||||||
{
|
{
|
||||||
if (!$this->checkFulltextSupport()) {
|
if (!$this->checkFulltextSupport()) {
|
||||||
@ -116,9 +111,6 @@ class ZZZSearchFormTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @skipUpgrade
|
|
||||||
*/
|
|
||||||
public function testPublishedPagesMatchedByTitle()
|
public function testPublishedPagesMatchedByTitle()
|
||||||
{
|
{
|
||||||
if (!$this->checkFulltextSupport()) {
|
if (!$this->checkFulltextSupport()) {
|
||||||
@ -149,9 +141,6 @@ class ZZZSearchFormTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @skipUpgrade
|
|
||||||
*/
|
|
||||||
public function testDoubleQuotesPublishedPagesMatchedByTitle()
|
public function testDoubleQuotesPublishedPagesMatchedByTitle()
|
||||||
{
|
{
|
||||||
if (!$this->checkFulltextSupport()) {
|
if (!$this->checkFulltextSupport()) {
|
||||||
@ -184,9 +173,6 @@ class ZZZSearchFormTest extends FunctionalTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @skipUpgrade
|
|
||||||
*/
|
|
||||||
public function testUnpublishedPagesNotIncluded()
|
public function testUnpublishedPagesNotIncluded()
|
||||||
{
|
{
|
||||||
if (!$this->checkFulltextSupport()) {
|
if (!$this->checkFulltextSupport()) {
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Tasks;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
|
||||||
use SilverStripe\CMS\Tasks\MigrateSiteTreeLinkingTask;
|
|
||||||
use SilverStripe\Dev\SapphireTest;
|
|
||||||
use SilverStripe\ORM\DataObject;
|
|
||||||
use SilverStripe\ORM\DB;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
|
|
||||||
class MigrateSiteTreeLinkingTaskTest extends SapphireTest
|
|
||||||
{
|
|
||||||
protected static $fixture_file = 'MigrateSiteTreeLinkingTaskTest.yml';
|
|
||||||
|
|
||||||
public static function setUpBeforeClass(): void
|
|
||||||
{
|
|
||||||
parent::setUpBeforeClass();
|
|
||||||
|
|
||||||
// Cover db reset in case parent did not start
|
|
||||||
if (!static::getExtraDataObjects()) {
|
|
||||||
DataObject::reset();
|
|
||||||
static::resetDBSchema(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure legacy SiteTree_LinkTracking table exists
|
|
||||||
DB::get_schema()->schemaUpdate(function () {
|
|
||||||
DB::require_table('SiteTree_LinkTracking', [
|
|
||||||
'SiteTreeID' => 'Int',
|
|
||||||
'ChildID' => 'Int',
|
|
||||||
'FieldName' => 'Varchar',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
// Manually bootstrap all Content blocks with soft coded IDs (raw sql to avoid save hooks)
|
|
||||||
$replacements = [
|
|
||||||
'$$ABOUTID$$' => $this->idFromFixture(SiteTree::class, 'about'),
|
|
||||||
'$$HOMEID$$' => $this->idFromFixture(SiteTree::class, 'home'),
|
|
||||||
'$$STAFFID$$' => $this->idFromFixture(SiteTree::class, 'staff'),
|
|
||||||
];
|
|
||||||
foreach (DB::query('SELECT "ID", "Content" FROM "SiteTree"') as $row) {
|
|
||||||
$id = (int)$row['ID'];
|
|
||||||
$content = str_replace(array_keys($replacements ?? []), array_values($replacements ?? []), $row['Content'] ?? '');
|
|
||||||
DB::prepared_query('UPDATE "SiteTree" SET "Content" = ? WHERE "ID" = ?', [$content, $id]);
|
|
||||||
}
|
|
||||||
DataObject::reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testLinkingMigration()
|
|
||||||
{
|
|
||||||
ob_start();
|
|
||||||
|
|
||||||
DB::quiet(false);
|
|
||||||
$task = new MigrateSiteTreeLinkingTask();
|
|
||||||
$task->run(null);
|
|
||||||
$this->assertStringContainsString(
|
|
||||||
"Migrated page links on 5 Pages",
|
|
||||||
ob_get_contents(),
|
|
||||||
'Rewritten links are correctly reported'
|
|
||||||
);
|
|
||||||
DB::quiet(true);
|
|
||||||
ob_end_clean();
|
|
||||||
|
|
||||||
// Query links for pages
|
|
||||||
/** @var SiteTree $home */
|
|
||||||
$home = $this->objFromFixture(SiteTree::class, 'home');
|
|
||||||
/** @var SiteTree $about */
|
|
||||||
$about = $this->objFromFixture(SiteTree::class, 'about');
|
|
||||||
/** @var SiteTree $staff */
|
|
||||||
$staff = $this->objFromFixture(SiteTree::class, 'staff');
|
|
||||||
/** @var SiteTree $action */
|
|
||||||
$action = $this->objFromFixture(SiteTree::class, 'action');
|
|
||||||
/** @var SiteTree $hash */
|
|
||||||
$hash = $this->objFromFixture(SiteTree::class, 'hash_link');
|
|
||||||
|
|
||||||
// Ensure all links are created
|
|
||||||
$this->assertListEquals([['ID' => $about->ID], ['ID' => $staff->ID]], $home->LinkTracking());
|
|
||||||
$this->assertListEquals([['ID' => $home->ID], ['ID' => $staff->ID]], $about->LinkTracking());
|
|
||||||
$this->assertListEquals([['ID' => $home->ID], ['ID' => $about->ID]], $staff->LinkTracking());
|
|
||||||
$this->assertListEquals([['ID' => $home->ID]], $action->LinkTracking());
|
|
||||||
$this->assertListEquals([['ID' => $home->ID], ['ID' => $about->ID]], $hash->LinkTracking());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
SilverStripe\CMS\Model\SiteTree:
|
|
||||||
home:
|
|
||||||
Title: Home Page
|
|
||||||
URLSegment: home
|
|
||||||
Content: '<a href="[sitetree_link,id=$$ABOUTID$$]">About</a><a href="[sitetree_link,id=$$STAFFID$$]">Staff</a><a href="http://silverstripe.org/">External Link</a><a name="anchor"></a>'
|
|
||||||
about:
|
|
||||||
Title: About Us
|
|
||||||
URLSegment: about
|
|
||||||
Content: '<a href="[sitetree_link,id=$$HOMEID$$]">Home</a><a href="[sitetree_link,id=$$STAFFID$$]">Staff</a><a name="second-anchor"></a>'
|
|
||||||
staff:
|
|
||||||
Title: Staff
|
|
||||||
URLSegment: staff
|
|
||||||
Content: '<a href="[sitetree_link,id=$$HOMEID$$]">Home</a><a href="[sitetree_link,id=$$ABOUTID$$]">About</a>'
|
|
||||||
Parent: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
action:
|
|
||||||
Title: Action Link
|
|
||||||
URLSegment: action
|
|
||||||
Content: '<a href="[sitetree_link,id=$$HOMEID$$]SearchForm">Search Form</a>'
|
|
||||||
hash_link:
|
|
||||||
Title: Hash Link
|
|
||||||
URLSegment: hash-link
|
|
||||||
Content: '<a href="[sitetree_link,id=$$HOMEID$$]#anchor">Home</a><a href="[sitetree_link,id=$$ABOUTID$$]#second-anchor">About</a>'
|
|
||||||
admin_link:
|
|
||||||
Title: Admin Link
|
|
||||||
URLSegment: admin-link
|
|
||||||
Content: '<a href="admin">Admin</a>'
|
|
||||||
no_links:
|
|
||||||
Title: No Links
|
|
||||||
URLSegment: No Links
|
|
||||||
|
|
||||||
SiteTree_LinkTracking:
|
|
||||||
home_about:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
FieldName: Content
|
|
||||||
home_staff:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.staff
|
|
||||||
FieldName: Content
|
|
||||||
about_home:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
FieldName: Content
|
|
||||||
about_staff:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.staff
|
|
||||||
FieldName: Content
|
|
||||||
staff_home:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.staff
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
FieldName: Content
|
|
||||||
staff_about:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.staff
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
FieldName: Content
|
|
||||||
action_home:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.action
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
FieldName: Content
|
|
||||||
hash_link_home:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.hash_link
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.home
|
|
||||||
FieldName: Content
|
|
||||||
hash_link_about:
|
|
||||||
SiteTreeID: =>SilverStripe\CMS\Model\SiteTree.hash_link
|
|
||||||
ChildID: =>SilverStripe\CMS\Model\SiteTree.about
|
|
||||||
FieldName: Content
|
|
@ -1,113 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace SilverStripe\CMS\Tests\Tasks;
|
|
||||||
|
|
||||||
use SilverStripe\CMS\Tasks\RemoveOrphanedPagesTask;
|
|
||||||
use SilverStripe\Versioned\Versioned;
|
|
||||||
use SilverStripe\Dev\FunctionalTest;
|
|
||||||
use SilverStripe\Dev\Deprecation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>Fixture tree</h2>
|
|
||||||
* <code>
|
|
||||||
* parent1_published
|
|
||||||
* child1_1_published
|
|
||||||
* grandchild1_1_1
|
|
||||||
* grandchild1_1_2_published
|
|
||||||
* grandchild1_1_3_orphaned
|
|
||||||
* grandchild1_1_4_orphaned_published
|
|
||||||
* child1_2_published
|
|
||||||
* child1_3_orphaned
|
|
||||||
* child1_4_orphaned_published
|
|
||||||
* parent2
|
|
||||||
* child2_1_published_orphaned // is orphaned because parent is not published
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* <h2>Cleaned up tree</h2>
|
|
||||||
* <code>
|
|
||||||
* parent1_published
|
|
||||||
* child1_1_published
|
|
||||||
* grandchild1_1_1
|
|
||||||
* grandchild1_1_2_published
|
|
||||||
* child2_1_published_orphaned
|
|
||||||
* parent2
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* @author Ingo Schommer (<firstname>@silverstripe.com), SilverStripe Ltd.
|
|
||||||
*/
|
|
||||||
class RemoveOrphanedPagesTaskTest extends FunctionalTest
|
|
||||||
{
|
|
||||||
protected static $fixture_file = 'RemoveOrphanedPagesTaskTest.yml';
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
if (Deprecation::isEnabled()) {
|
|
||||||
$this->markTestSkipped('Test calls deprecated code');
|
|
||||||
}
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$parent1_published = $this->objFromFixture('Page', 'parent1_published');
|
|
||||||
$parent1_published->publishSingle();
|
|
||||||
|
|
||||||
$child1_1_published = $this->objFromFixture('Page', 'child1_1_published');
|
|
||||||
$child1_1_published->publishSingle();
|
|
||||||
|
|
||||||
$child1_2_published = $this->objFromFixture('Page', 'child1_2_published');
|
|
||||||
$child1_2_published->publishSingle();
|
|
||||||
|
|
||||||
$child1_3_orphaned = $this->objFromFixture('Page', 'child1_3_orphaned');
|
|
||||||
$child1_3_orphaned->ParentID = 9999;
|
|
||||||
$child1_3_orphaned->write();
|
|
||||||
|
|
||||||
$child1_4_orphaned_published = $this->objFromFixture('Page', 'child1_4_orphaned_published');
|
|
||||||
$child1_4_orphaned_published->ParentID = 9999;
|
|
||||||
$child1_4_orphaned_published->write();
|
|
||||||
$child1_4_orphaned_published->publishSingle();
|
|
||||||
|
|
||||||
$grandchild1_1_2_published = $this->objFromFixture('Page', 'grandchild1_1_2_published');
|
|
||||||
$grandchild1_1_2_published->publishSingle();
|
|
||||||
|
|
||||||
$grandchild1_1_3_orphaned = $this->objFromFixture('Page', 'grandchild1_1_3_orphaned');
|
|
||||||
$grandchild1_1_3_orphaned->ParentID = 9999;
|
|
||||||
$grandchild1_1_3_orphaned->write();
|
|
||||||
|
|
||||||
$grandchild1_1_4_orphaned_published = $this->objFromFixture(
|
|
||||||
'Page',
|
|
||||||
'grandchild1_1_4_orphaned_published'
|
|
||||||
);
|
|
||||||
$grandchild1_1_4_orphaned_published->ParentID = 9999;
|
|
||||||
$grandchild1_1_4_orphaned_published->write();
|
|
||||||
$grandchild1_1_4_orphaned_published->publishSingle();
|
|
||||||
|
|
||||||
$child2_1_published_orphaned = $this->objFromFixture('Page', 'child2_1_published_orphaned');
|
|
||||||
$child2_1_published_orphaned->publishSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetOrphansByStage()
|
|
||||||
{
|
|
||||||
// all orphans
|
|
||||||
$child1_3_orphaned = $this->objFromFixture('Page', 'child1_3_orphaned');
|
|
||||||
$child1_4_orphaned_published = $this->objFromFixture('Page', 'child1_4_orphaned_published');
|
|
||||||
$grandchild1_1_3_orphaned = $this->objFromFixture('Page', 'grandchild1_1_3_orphaned');
|
|
||||||
$grandchild1_1_4_orphaned_published = $this->objFromFixture(
|
|
||||||
'Page',
|
|
||||||
'grandchild1_1_4_orphaned_published'
|
|
||||||
);
|
|
||||||
$child2_1_published_orphaned = $this->objFromFixture('Page', 'child2_1_published_orphaned');
|
|
||||||
|
|
||||||
$task = singleton(RemoveOrphanedPagesTask::class);
|
|
||||||
$orphans = $task->getOrphanedPages();
|
|
||||||
$orphanIDs = $orphans->column('ID');
|
|
||||||
sort($orphanIDs);
|
|
||||||
$compareIDs = [
|
|
||||||
$child1_3_orphaned->ID,
|
|
||||||
$child1_4_orphaned_published->ID,
|
|
||||||
$grandchild1_1_3_orphaned->ID,
|
|
||||||
$grandchild1_1_4_orphaned_published->ID,
|
|
||||||
$child2_1_published_orphaned->ID
|
|
||||||
];
|
|
||||||
sort($compareIDs);
|
|
||||||
|
|
||||||
$this->assertEquals($orphanIDs, $compareIDs);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
Page:
|
|
||||||
parent1_published:
|
|
||||||
Title: Parent1
|
|
||||||
child1_1_published:
|
|
||||||
Title: Child1.1
|
|
||||||
Parent: =>Page.parent1_published
|
|
||||||
child1_2_published:
|
|
||||||
Title: Child1.2
|
|
||||||
Parent: =>Page.parent1_published
|
|
||||||
child1_3_orphaned:
|
|
||||||
Title: Child1.3
|
|
||||||
Parent: =>Page.parent1_published
|
|
||||||
child1_4_orphaned_published:
|
|
||||||
Title: Child1.4
|
|
||||||
Parent: =>Page.parent1_published
|
|
||||||
grandchild1_1_1:
|
|
||||||
Title: Grandchild1.1.1
|
|
||||||
Parent: =>Page.child1_1_published
|
|
||||||
grandchild1_1_2_published:
|
|
||||||
Title: Grandchild1.1.2
|
|
||||||
Parent: =>Page.child1_1_published
|
|
||||||
grandchild1_1_3_orphaned:
|
|
||||||
Title: Grandchild1.1.3
|
|
||||||
Parent: =>Page.child1_1_published
|
|
||||||
grandchild1_1_4_orphaned_published:
|
|
||||||
Title: Grandchild1.1.4
|
|
||||||
Parent: =>Page.child1_1_published
|
|
||||||
parent2:
|
|
||||||
Title: Parent2
|
|
||||||
child2_1_published_orphaned:
|
|
||||||
Title: Child2.1
|
|
||||||
Parent: =>Page.parent2
|
|
@ -1,19 +1,8 @@
|
|||||||
const Path = require('path');
|
const Path = require('path');
|
||||||
const webpackConfig = require('@silverstripe/webpack-config');
|
const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config');
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
const {
|
|
||||||
resolveJS,
|
|
||||||
externalJS,
|
|
||||||
moduleJS,
|
|
||||||
pluginJS,
|
|
||||||
moduleCSS,
|
|
||||||
pluginCSS,
|
|
||||||
} = webpackConfig;
|
|
||||||
|
|
||||||
const ENV = process.env.NODE_ENV;
|
|
||||||
const PATHS = {
|
const PATHS = {
|
||||||
MODULES: 'node_modules',
|
|
||||||
FILES_PATH: '../',
|
|
||||||
ROOT: Path.resolve(),
|
ROOT: Path.resolve(),
|
||||||
SRC: Path.resolve('client/src'),
|
SRC: Path.resolve('client/src'),
|
||||||
DIST: Path.resolve('client/dist'),
|
DIST: Path.resolve('client/dist'),
|
||||||
@ -21,46 +10,37 @@ const PATHS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const config = [
|
const config = [
|
||||||
{
|
// Main JS bundles
|
||||||
name: 'js',
|
new JavascriptWebpackConfig('js', PATHS, 'silverstripe/cms')
|
||||||
entry: {
|
.setEntry({
|
||||||
bundle: `${PATHS.SRC}/bundles/bundle.js`,
|
bundle: `${PATHS.SRC}/bundles/bundle.js`,
|
||||||
// See https://github.com/webpack/webpack/issues/300#issuecomment-45313650
|
|
||||||
SilverStripeNavigator: `${PATHS.LEGACY_SRC}/SilverStripeNavigator.js`,
|
SilverStripeNavigator: `${PATHS.LEGACY_SRC}/SilverStripeNavigator.js`,
|
||||||
'TinyMCE_sslink-internal': `${PATHS.LEGACY_SRC}/TinyMCE_sslink-internal.js`,
|
'TinyMCE_sslink-internal': `${PATHS.LEGACY_SRC}/TinyMCE_sslink-internal.js`,
|
||||||
'TinyMCE_sslink-anchor': `${PATHS.LEGACY_SRC}/TinyMCE_sslink-anchor.js`,
|
'TinyMCE_sslink-anchor': `${PATHS.LEGACY_SRC}/TinyMCE_sslink-anchor.js`,
|
||||||
},
|
})
|
||||||
output: {
|
.mergeConfig({
|
||||||
path: PATHS.DIST,
|
plugins: [
|
||||||
filename: 'js/[name].js',
|
new CopyWebpackPlugin({
|
||||||
},
|
patterns: [
|
||||||
devtool: (ENV !== 'production') ? 'source-map' : '',
|
{
|
||||||
resolve: resolveJS(ENV, PATHS),
|
from: `${PATHS.SRC}/images`,
|
||||||
externals: externalJS(ENV, PATHS),
|
to: `${PATHS.DIST}/images`
|
||||||
module: moduleJS(ENV, PATHS),
|
},
|
||||||
plugins: pluginJS(ENV, PATHS).concat([
|
]
|
||||||
new CopyWebpackPlugin([
|
}),
|
||||||
{ from: 'client/src/images', to: 'images' },
|
],
|
||||||
])
|
})
|
||||||
])
|
.getConfig(),
|
||||||
},
|
// sass to css
|
||||||
{
|
new CssWebpackConfig('css', PATHS)
|
||||||
name: 'css',
|
.setEntry({
|
||||||
entry: {
|
|
||||||
bundle: `${PATHS.SRC}/styles/bundle.scss`,
|
bundle: `${PATHS.SRC}/styles/bundle.scss`,
|
||||||
SilverStripeNavigator: `${PATHS.SRC}/styles/SilverStripeNavigator.scss`,
|
SilverStripeNavigator: `${PATHS.SRC}/styles/SilverStripeNavigator.scss`,
|
||||||
},
|
})
|
||||||
output: {
|
.getConfig(),
|
||||||
path: PATHS.DIST,
|
|
||||||
filename: 'styles/[name].css',
|
|
||||||
},
|
|
||||||
devtool: (ENV !== 'production') ? 'source-map' : '',
|
|
||||||
module: moduleCSS(ENV, PATHS),
|
|
||||||
plugins: pluginCSS(ENV, PATHS),
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Use WEBPACK_CHILD=js or WEBPACK_CHILD=css env var to run a single config
|
// Use WEBPACK_CHILD=js or WEBPACK_CHILD=css env var to run a single config
|
||||||
module.exports = (process.env.WEBPACK_CHILD)
|
module.exports = (process.env.WEBPACK_CHILD)
|
||||||
? config.find((entry) => entry.name === process.env.WEBPACK_CHILD)
|
? config.find((entry) => entry.name === process.env.WEBPACK_CHILD)
|
||||||
: module.exports = config;
|
: config;
|
||||||
|
Loading…
Reference in New Issue
Block a user