mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Merge pull request #1381 from open-sausages/pulls/4.0/versioned-asset-control
API Support versioned File management
This commit is contained in:
commit
94fcfa48ed
@ -7,3 +7,6 @@ Controller:
|
|||||||
Form:
|
Form:
|
||||||
extensions:
|
extensions:
|
||||||
- ErrorPageControllerExtension
|
- ErrorPageControllerExtension
|
||||||
|
File:
|
||||||
|
extensions:
|
||||||
|
- ErrorPageFileExtension
|
||||||
|
@ -39,7 +39,7 @@ class CMSBatchAction_Unpublish extends CMSBatchAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function applicablePages($ids) {
|
public function applicablePages($ids) {
|
||||||
return $this->applicablePagesHelper($ids, 'canDeleteFromLive', false, true);
|
return $this->applicablePagesHelper($ids, 'canUnpublish', false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +183,14 @@ class CMSBatchAction_DeleteFromLive extends CMSBatchAction {
|
|||||||
'deleted'=>array()
|
'deleted'=>array()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** @var SiteTree $page */
|
||||||
foreach($pages as $page) {
|
foreach($pages as $page) {
|
||||||
$id = $page->ID;
|
$id = $page->ID;
|
||||||
|
|
||||||
// Perform the action
|
// Perform the action
|
||||||
if($page->canDelete()) $page->doDeleteFromLive();
|
if($page->canUnpublish()) {
|
||||||
|
$page->doUnpublish();
|
||||||
|
}
|
||||||
|
|
||||||
// check to see if the record exists on the stage site, if it doesn't remove the tree node
|
// check to see if the record exists on the stage site, if it doesn't remove the tree node
|
||||||
$stageRecord = Versioned::get_one_by_stage( 'SiteTree', 'Stage', array(
|
$stageRecord = Versioned::get_one_by_stage( 'SiteTree', 'Stage', array(
|
||||||
|
@ -63,6 +63,7 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
|
|||||||
public function init() {
|
public function init() {
|
||||||
parent::init();
|
parent::init();
|
||||||
|
|
||||||
|
Versioned::reading_stage("Stage");
|
||||||
|
|
||||||
Requirements::javascript(CMS_DIR . "/javascript/dist/AssetAdmin.js");
|
Requirements::javascript(CMS_DIR . "/javascript/dist/AssetAdmin.js");
|
||||||
Requirements::add_i18n_javascript(CMS_DIR . '/javascript/lang', false, true);
|
Requirements::add_i18n_javascript(CMS_DIR . '/javascript/lang', false, true);
|
||||||
|
@ -533,7 +533,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*
|
*
|
||||||
* @param int $id Record ID
|
* @param int $id Record ID
|
||||||
* @param int $versionID optional Version id of the given record
|
* @param int $versionID optional Version id of the given record
|
||||||
* @return DataObject
|
* @return SiteTree
|
||||||
*/
|
*/
|
||||||
public function getRecord($id, $versionID = null) {
|
public function getRecord($id, $versionID = null) {
|
||||||
$treeClass = $this->stat('tree_class');
|
$treeClass = $this->stat('tree_class');
|
||||||
@ -591,7 +591,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
* @return CMSForm
|
* @return CMSForm
|
||||||
*/
|
*/
|
||||||
public function getEditForm($id = null, $fields = null) {
|
public function getEditForm($id = null, $fields = null) {
|
||||||
|
|
||||||
if(!$id) $id = $this->currentPageID();
|
if(!$id) $id = $this->currentPageID();
|
||||||
$form = parent::getEditForm($id);
|
$form = parent::getEditForm($id);
|
||||||
|
|
||||||
@ -604,7 +603,6 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
if($record) {
|
if($record) {
|
||||||
$deletedFromStage = $record->getIsDeletedFromStage();
|
$deletedFromStage = $record->getIsDeletedFromStage();
|
||||||
$deleteFromLive = !$record->getExistsOnLive();
|
|
||||||
|
|
||||||
$fields->push($idField = new HiddenField("ID", false, $id));
|
$fields->push($idField = new HiddenField("ID", false, $id));
|
||||||
// Necessary for different subsites
|
// Necessary for different subsites
|
||||||
@ -974,13 +972,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
*/
|
*/
|
||||||
public function deletefromlive($data, $form) {
|
public function deletefromlive($data, $form) {
|
||||||
Versioned::reading_stage('Live');
|
Versioned::reading_stage('Live');
|
||||||
$record = DataObject::get_by_id("SiteTree", $data['ID']);
|
|
||||||
if($record && !($record->canDelete() && $record->canDeleteFromLive())) return Security::permissionFailure($this);
|
|
||||||
|
|
||||||
$descRemoved = '';
|
/** @var SiteTree $record */
|
||||||
|
$record = DataObject::get_by_id("SiteTree", $data['ID']);
|
||||||
|
if($record && !($record->canDelete() && $record->canUnpublish())) {
|
||||||
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
|
|
||||||
$descendantsRemoved = 0;
|
$descendantsRemoved = 0;
|
||||||
$recordTitle = $record->Title;
|
$recordTitle = $record->Title;
|
||||||
$recordID = $record->ID;
|
|
||||||
|
|
||||||
// before deleting the records, get the descendants of this tree
|
// before deleting the records, get the descendants of this tree
|
||||||
if($record) {
|
if($record) {
|
||||||
@ -989,13 +989,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
// then delete them from the live site too
|
// then delete them from the live site too
|
||||||
$descendantsRemoved = 0;
|
$descendantsRemoved = 0;
|
||||||
foreach( $descendantIDs as $descID )
|
foreach( $descendantIDs as $descID )
|
||||||
|
/** @var SiteTree $descendant */
|
||||||
if( $descendant = DataObject::get_by_id('SiteTree', $descID) ) {
|
if( $descendant = DataObject::get_by_id('SiteTree', $descID) ) {
|
||||||
$descendant->doDeleteFromLive();
|
$descendant->doUnpublish();
|
||||||
$descendantsRemoved++;
|
$descendantsRemoved++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the record
|
// delete the record
|
||||||
$record->doDeleteFromLive();
|
$record->doUnpublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
Versioned::reading_stage('Stage');
|
Versioned::reading_stage('Stage');
|
||||||
@ -1098,8 +1099,8 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
/**
|
/**
|
||||||
* Delete this page from both live and stage
|
* Delete this page from both live and stage
|
||||||
*
|
*
|
||||||
* @param type $data
|
* @param array $data
|
||||||
* @param type $form
|
* @param Form $form
|
||||||
*/
|
*/
|
||||||
public function archive($data, $form) {
|
public function archive($data, $form) {
|
||||||
$id = $data['ID'];
|
$id = $data['ID'];
|
||||||
@ -1131,10 +1132,15 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
|||||||
|
|
||||||
public function unpublish($data, $form) {
|
public function unpublish($data, $form) {
|
||||||
$className = $this->stat('tree_class');
|
$className = $this->stat('tree_class');
|
||||||
|
/** @var SiteTree $record */
|
||||||
$record = DataObject::get_by_id($className, $data['ID']);
|
$record = DataObject::get_by_id($className, $data['ID']);
|
||||||
|
|
||||||
if($record && !$record->canDeleteFromLive()) return Security::permissionFailure($this);
|
if($record && !$record->canUnpublish()) {
|
||||||
if(!$record || !$record->ID) throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404);
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
|
if(!$record || !$record->ID) {
|
||||||
|
throw new SS_HTTPResponse_Exception("Bad record ID #" . (int)$data['ID'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
$record->doUnpublish();
|
$record->doUnpublish();
|
||||||
|
|
||||||
|
@ -8,6 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
class ErrorPageControllerExtension extends Extension {
|
class ErrorPageControllerExtension extends Extension {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@see RequestHandler::httpError}
|
||||||
|
*
|
||||||
|
* @param int $statusCode
|
||||||
|
* @param SS_HTTPRequest $request
|
||||||
|
* @throws SS_HTTPResponse_Exception
|
||||||
|
*/
|
||||||
public function onBeforeHTTPError($statusCode, $request) {
|
public function onBeforeHTTPError($statusCode, $request) {
|
||||||
$response = ErrorPage::response_for($statusCode);
|
$response = ErrorPage::response_for($statusCode);
|
||||||
if($response) {
|
if($response) {
|
||||||
|
18
code/controllers/ErrorPageFileExtension.php
Normal file
18
code/controllers/ErrorPageFileExtension.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates {@see File} with ErrorPage support
|
||||||
|
*/
|
||||||
|
class ErrorPageFileExtension extends DataExtension {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@see File::handle_shortcode}
|
||||||
|
*
|
||||||
|
* @param int $statusCode HTTP Error code
|
||||||
|
* @return DataObject Substitute object suitable for handling the given error code
|
||||||
|
*/
|
||||||
|
public function getErrorRecordFor($statusCode) {
|
||||||
|
return ErrorPage::get()->filter("ErrorCode", $statusCode)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,7 +26,6 @@
|
|||||||
*
|
*
|
||||||
* @method ManyManyList ViewerGroups List of groups that can view this object.
|
* @method ManyManyList ViewerGroups List of groups that can view this object.
|
||||||
* @method ManyManyList EditorGroups List of groups that can edit this object.
|
* @method ManyManyList EditorGroups List of groups that can edit this object.
|
||||||
* @method ManyManyList BackLinkTracking List of site pages that link to this page.
|
|
||||||
*
|
*
|
||||||
* @mixin Hierarchy
|
* @mixin Hierarchy
|
||||||
* @mixin Versioned
|
* @mixin Versioned
|
||||||
@ -129,21 +128,10 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
);
|
);
|
||||||
|
|
||||||
private static $many_many = array(
|
private static $many_many = array(
|
||||||
"LinkTracking" => "SiteTree",
|
|
||||||
"ImageTracking" => "File",
|
|
||||||
"ViewerGroups" => "Group",
|
"ViewerGroups" => "Group",
|
||||||
"EditorGroups" => "Group",
|
"EditorGroups" => "Group",
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $belongs_many_many = array(
|
|
||||||
"BackLinkTracking" => "SiteTree"
|
|
||||||
);
|
|
||||||
|
|
||||||
private static $many_many_extraFields = array(
|
|
||||||
"LinkTracking" => array("FieldName" => "Varchar"),
|
|
||||||
"ImageTracking" => array("FieldName" => "Varchar")
|
|
||||||
);
|
|
||||||
|
|
||||||
private static $casting = array(
|
private static $casting = array(
|
||||||
"Breadcrumbs" => "HTMLText",
|
"Breadcrumbs" => "HTMLText",
|
||||||
"LastEdited" => "SS_Datetime",
|
"LastEdited" => "SS_Datetime",
|
||||||
@ -1080,37 +1068,19 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function should return true if the current user can publish this page. It can be overloaded to customise
|
* @deprecated
|
||||||
* the security model for an application.
|
|
||||||
*
|
|
||||||
* Denies permission if any of the following conditions is true:
|
|
||||||
* - canPublish() on any extension returns false
|
|
||||||
* - canEdit() returns false
|
|
||||||
*
|
|
||||||
* @uses SiteTreeExtension->canPublish()
|
|
||||||
*
|
|
||||||
* @param Member $member
|
|
||||||
* @return bool True if the current user can publish this page.
|
|
||||||
*/
|
*/
|
||||||
public function canPublish($member = null) {
|
|
||||||
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
|
||||||
|
|
||||||
// Standard mechanism for accepting permission changes from extensions
|
|
||||||
$extended = $this->extendedCan('canPublish', $member);
|
|
||||||
if($extended !== null) return $extended;
|
|
||||||
|
|
||||||
// Normal case - fail over to canEdit()
|
|
||||||
return $this->canEdit($member);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canDeleteFromLive($member = null) {
|
public function canDeleteFromLive($member = null) {
|
||||||
// Standard mechanism for accepting permission changes from extensions
|
Deprecation::notice('4.0', 'Use canUnpublish');
|
||||||
$extended = $this->extendedCan('canDeleteFromLive', $member);
|
|
||||||
if($extended !==null) return $extended;
|
|
||||||
|
|
||||||
return $this->canPublish($member);
|
// Deprecated extension
|
||||||
|
$extended = $this->extendedCan('canDeleteFromLive', $member);
|
||||||
|
if($extended !== null) {
|
||||||
|
Deprecation::notice('4.0', 'Use canUnpublish in your extension instead');
|
||||||
|
return $extended;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->canUnpublish($member);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1552,6 +1522,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger synchronisation of link tracking
|
||||||
|
*
|
||||||
|
* {@see SiteTreeLinkTracking::augmentSyncLinkTracking}
|
||||||
|
*/
|
||||||
public function syncLinkTracking() {
|
public function syncLinkTracking() {
|
||||||
$this->extend('augmentSyncLinkTracking');
|
$this->extend('augmentSyncLinkTracking');
|
||||||
}
|
}
|
||||||
@ -1737,43 +1712,42 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrites any linked images on this page.
|
* Rewrites any linked images on this page without creating a new version record.
|
||||||
* Non-image files should be linked via shortcodes
|
* Non-image files should be linked via shortcodes
|
||||||
* Triggers the onRenameLinkedAsset action on extensions.
|
* Triggers the onRenameLinkedAsset action on extensions.
|
||||||
* TODO: This doesn't work for HTMLText fields on other tables.
|
*
|
||||||
|
* @todo Implement image shortcodes and remove this feature
|
||||||
*/
|
*/
|
||||||
public function rewriteFileLinks() {
|
public function rewriteFileLinks() {
|
||||||
|
// Skip live stage
|
||||||
|
if(\Versioned::current_stage() === \Versioned::get_live_stage()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update the content without actually creating a new version
|
// Update the content without actually creating a new version
|
||||||
foreach(array("SiteTree_Live", "SiteTree") as $table) {
|
foreach($this->db() as $fieldName => $fieldType) {
|
||||||
// Published site
|
// Skip if non HTML or if empty
|
||||||
$published = DB::prepared_query(
|
if ($fieldType !== 'HTMLText') {
|
||||||
"SELECT * FROM \"$table\" WHERE \"ID\" = ?",
|
continue;
|
||||||
array($this->ID)
|
|
||||||
)->record();
|
|
||||||
$origPublished = $published;
|
|
||||||
|
|
||||||
foreach($this->db() as $fieldName => $fieldType) {
|
|
||||||
// Skip if non HTML or if empty
|
|
||||||
if ($fieldType !== 'HTMLText' || empty($published[$fieldName])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regenerate content
|
|
||||||
$content = Image::regenerate_html_links($published[$fieldName]);
|
|
||||||
if($content === $published[$fieldName]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = sprintf('UPDATE "%s" SET "%s" = ? WHERE "ID" = ?', $table, $fieldName);
|
|
||||||
DB::prepared_query($query, array($content, $this->ID));
|
|
||||||
|
|
||||||
// Tell static caching to update itself
|
|
||||||
if($table == 'SiteTree_Live') {
|
|
||||||
$publishedClass = $origPublished['ClassName'];
|
|
||||||
$origPublishedObj = new $publishedClass($origPublished);
|
|
||||||
$this->invokeWithExtensions('onRenameLinkedAsset', $origPublishedObj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$fieldValue = $this->{$fieldName};
|
||||||
|
if(empty($fieldValue)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regenerate content
|
||||||
|
$content = Image::regenerate_html_links($fieldValue);
|
||||||
|
if($content === $fieldValue) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write content directly without updating linked assets
|
||||||
|
$table = ClassInfo::table_for_object_field($this, $fieldName);
|
||||||
|
$query = sprintf('UPDATE "%s" SET "%s" = ? WHERE "ID" = ?', $table, $fieldName);
|
||||||
|
DB::prepared_query($query, array($content, $this->ID));
|
||||||
|
|
||||||
|
// Update linked assets
|
||||||
|
$this->invokeWithExtensions('onRenameLinkedAsset');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2267,7 +2241,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
return $actions;
|
return $actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->isPublished() && $this->canPublish() && !$this->getIsDeletedFromStage() && $this->canDeleteFromLive()) {
|
if($this->isPublished() && $this->canPublish() && !$this->getIsDeletedFromStage() && $this->canUnpublish()) {
|
||||||
// "unpublish"
|
// "unpublish"
|
||||||
$moreOptions->push(
|
$moreOptions->push(
|
||||||
FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')
|
FormAction::create('unpublish', _t('SiteTree.BUTTONUNPUBLISH', 'Unpublish'), 'delete')
|
||||||
@ -2292,7 +2266,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
if($existsOnLive) {
|
if($existsOnLive) {
|
||||||
// "restore"
|
// "restore"
|
||||||
$majorActions->push(FormAction::create('revert',_t('CMSMain.RESTORE','Restore')));
|
$majorActions->push(FormAction::create('revert',_t('CMSMain.RESTORE','Restore')));
|
||||||
if($this->canDelete() && $this->canDeleteFromLive()) {
|
if($this->canDelete() && $this->canUnpublish()) {
|
||||||
// "delete from live"
|
// "delete from live"
|
||||||
$majorActions->push(
|
$majorActions->push(
|
||||||
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))
|
FormAction::create('deletefromlive',_t('CMSMain.DELETEFP','Delete'))
|
||||||
@ -2428,11 +2402,13 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
/**
|
/**
|
||||||
* Unpublish this page - remove it from the live site
|
* Unpublish this page - remove it from the live site
|
||||||
*
|
*
|
||||||
|
* Overrides {@see Versioned::doUnpublish()}
|
||||||
|
*
|
||||||
* @uses SiteTreeExtension->onBeforeUnpublish()
|
* @uses SiteTreeExtension->onBeforeUnpublish()
|
||||||
* @uses SiteTreeExtension->onAfterUnpublish()
|
* @uses SiteTreeExtension->onAfterUnpublish()
|
||||||
*/
|
*/
|
||||||
public function doUnpublish() {
|
public function doUnpublish() {
|
||||||
if(!$this->canDeleteFromLive()) return false;
|
if(!$this->canUnpublish()) return false;
|
||||||
if(!$this->ID) return false;
|
if(!$this->ID) return false;
|
||||||
|
|
||||||
$this->invokeWithExtensions('onBeforeUnpublish', $this);
|
$this->invokeWithExtensions('onBeforeUnpublish', $this);
|
||||||
@ -2550,58 +2526,10 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the page from both live and stage
|
* @deprecated
|
||||||
*
|
|
||||||
* @return bool Success
|
|
||||||
*/
|
|
||||||
public function doArchive() {
|
|
||||||
$this->invokeWithExtensions('onBeforeArchive', $this);
|
|
||||||
|
|
||||||
if($this->doUnpublish()) {
|
|
||||||
$this->delete();
|
|
||||||
$this->invokeWithExtensions('onAfterArchive', $this);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the current user is allowed to archive this page.
|
|
||||||
* If extended, ensure that both canDelete and canDeleteFromLive are extended also
|
|
||||||
*
|
|
||||||
* @param Member $member
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function canArchive($member = null) {
|
|
||||||
if(!$member) {
|
|
||||||
$member = Member::currentUser();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Standard mechanism for accepting permission changes from extensions
|
|
||||||
$extended = $this->extendedCan('canArchive', $member);
|
|
||||||
if($extended !== null) {
|
|
||||||
return $extended;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this page can be deleted
|
|
||||||
if(!$this->canDelete($member)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If published, check if we can delete from live
|
|
||||||
if($this->ExistsOnLive && !$this->canDeleteFromLive($member)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synonym of {@link doUnpublish}
|
|
||||||
*/
|
*/
|
||||||
public function doDeleteFromLive() {
|
public function doDeleteFromLive() {
|
||||||
|
Deprecation::notice("4.0", "Use doUnpublish instead");
|
||||||
return $this->doUnpublish();
|
return $this->doUnpublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2622,21 +2550,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
return stripos($this->ID, 'new') === 0;
|
return stripos($this->ID, 'new') === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this page has been published.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isPublished() {
|
|
||||||
if($this->isNew())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (DB::prepared_query("SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($this->ID))->value())
|
|
||||||
? true
|
|
||||||
: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the class dropdown used in the CMS to change the class of a page. This returns the list of options in the
|
* Get the class dropdown used in the CMS to change the class of a page. This returns the list of options in the
|
||||||
* dropdown as a Map from class name to singular name. Filters by {@link SiteTree->canCreate()}, as well as
|
* dropdown as a Map from class name to singular name. Filters by {@link SiteTree->canCreate()}, as well as
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Extension applied to {@see File} object to track links to {@see SiteTree} records.
|
||||||
|
*
|
||||||
|
* {@see SiteTreeLinkTracking} for the extension applied to {@see SiteTree}
|
||||||
|
*
|
||||||
|
* Note that since both SiteTree and File are versioned, LinkTracking and ImageTracking will
|
||||||
|
* only be enabled for the Stage record.
|
||||||
|
*
|
||||||
|
* @property File $owner
|
||||||
|
*
|
||||||
* @package cms
|
* @package cms
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
class SiteTreeFileExtension extends DataExtension {
|
class SiteTreeFileExtension extends DataExtension {
|
||||||
|
|
||||||
private static $belongs_many_many = array(
|
private static $belongs_many_many = array(
|
||||||
'BackLinkTracking' => 'SiteTree'
|
'BackLinkTracking' => 'SiteTree.ImageTracking' // {@see SiteTreeLinkTracking}
|
||||||
);
|
);
|
||||||
|
|
||||||
public function updateCMSFields(FieldList $fields) {
|
public function updateCMSFields(FieldList $fields) {
|
||||||
@ -16,8 +26,8 @@ class SiteTreeFileExtension extends DataExtension {
|
|||||||
_t('AssetTableField.BACKLINKCOUNT', 'Used on:'),
|
_t('AssetTableField.BACKLINKCOUNT', 'Used on:'),
|
||||||
$this->BackLinkTracking()->Count() . ' ' . _t('AssetTableField.PAGES', 'page(s)')
|
$this->BackLinkTracking()->Count() . ' ' . _t('AssetTableField.PAGES', 'page(s)')
|
||||||
)
|
)
|
||||||
->addExtraClass('cms-description-toggle')
|
->addExtraClass('cms-description-toggle')
|
||||||
->setDescription($this->BackLinkHTMLList()),
|
->setDescription($this->BackLinkHTMLList()),
|
||||||
'LastEdited'
|
'LastEdited'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -32,8 +42,8 @@ class SiteTreeFileExtension extends DataExtension {
|
|||||||
'SiteTreeFileExtension.BACKLINK_LIST_DESCRIPTION',
|
'SiteTreeFileExtension.BACKLINK_LIST_DESCRIPTION',
|
||||||
'This list shows all pages where the file has been added through a WYSIWYG editor.'
|
'This list shows all pages where the file has been added through a WYSIWYG editor.'
|
||||||
) . '</em>';
|
) . '</em>';
|
||||||
$html .= '<ul>';
|
|
||||||
|
|
||||||
|
$html .= '<ul>';
|
||||||
foreach ($this->BackLinkTracking() as $backLink) {
|
foreach ($this->BackLinkTracking() as $backLink) {
|
||||||
// Add the page link and CMS link
|
// Add the page link and CMS link
|
||||||
$html .= sprintf(
|
$html .= sprintf(
|
||||||
@ -44,17 +54,14 @@ class SiteTreeFileExtension extends DataExtension {
|
|||||||
_t('SiteTreeFileExtension.EDIT', 'Edit')
|
_t('SiteTreeFileExtension.EDIT', 'Edit')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$html .= '</ul>';
|
||||||
|
|
||||||
return $html .= '</ul>';
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend through {@link updateBackLinkTracking()} in your own {@link Extension}.
|
* Extend through {@link updateBackLinkTracking()} in your own {@link Extension}.
|
||||||
*
|
*
|
||||||
* @param string|array $filter
|
|
||||||
* @param string $sort
|
|
||||||
* @param string $join
|
|
||||||
* @param string $limit
|
|
||||||
* @return ManyManyList
|
* @return ManyManyList
|
||||||
*/
|
*/
|
||||||
public function BackLinkTracking() {
|
public function BackLinkTracking() {
|
||||||
@ -88,39 +95,48 @@ class SiteTreeFileExtension extends DataExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates link tracking.
|
* Updates link tracking in the current stage.
|
||||||
*/
|
*/
|
||||||
public function onAfterDelete() {
|
public function onAfterDelete() {
|
||||||
|
// Skip live stage
|
||||||
|
if(\Versioned::current_stage() === \Versioned::get_live_stage()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We query the explicit ID list, because BackLinkTracking will get modified after the stage
|
// We query the explicit ID list, because BackLinkTracking will get modified after the stage
|
||||||
// site does its thing
|
// site does its thing
|
||||||
$brokenPageIDs = $this->owner->BackLinkTracking()->column("ID");
|
$brokenPageIDs = $this->owner->BackLinkTracking()->column("ID");
|
||||||
if($brokenPageIDs) {
|
if($brokenPageIDs) {
|
||||||
$origStage = Versioned::current_stage();
|
// This will syncLinkTracking on the same stage as this file
|
||||||
|
|
||||||
// This will syncLinkTracking on draft
|
|
||||||
Versioned::reading_stage('Stage');
|
|
||||||
$brokenPages = DataObject::get('SiteTree')->byIDs($brokenPageIDs);
|
$brokenPages = DataObject::get('SiteTree')->byIDs($brokenPageIDs);
|
||||||
foreach($brokenPages as $brokenPage) {
|
foreach($brokenPages as $brokenPage) {
|
||||||
$brokenPage->write();
|
$brokenPage->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will syncLinkTracking on published
|
|
||||||
Versioned::reading_stage('Live');
|
|
||||||
$liveBrokenPages = DataObject::get('SiteTree')->byIDs($brokenPageIDs);
|
|
||||||
foreach($liveBrokenPages as $brokenPage) {
|
|
||||||
$brokenPage->write();
|
|
||||||
}
|
|
||||||
|
|
||||||
Versioned::reading_stage($origStage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onAfterWrite() {
|
||||||
|
// Update any database references in the current stage
|
||||||
|
$this->updateLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onAfterVersionedPublish() {
|
||||||
|
// Ensure that ->updateLinks is invoked on the draft record
|
||||||
|
// after ->doPublish() is invoked.
|
||||||
|
$this->updateLinks();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrite links to the $old file to now point to the $new file.
|
* Rewrite links to the $old file to now point to the $new file.
|
||||||
*
|
*
|
||||||
* @uses SiteTree->rewriteFileID()
|
* @uses SiteTree->rewriteFileID()
|
||||||
*/
|
*/
|
||||||
public function updateLinks() {
|
public function updateLinks() {
|
||||||
|
// Skip live stage
|
||||||
|
if(\Versioned::current_stage() === \Versioned::get_live_stage()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(class_exists('Subsite')) {
|
if(class_exists('Subsite')) {
|
||||||
Subsite::disable_subsite_filter(true);
|
Subsite::disable_subsite_filter(true);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
* referenced in any HTMLText fields, and two booleans to indicate if there are any broken links. Call
|
* referenced in any HTMLText fields, and two booleans to indicate if there are any broken links. Call
|
||||||
* augmentSyncLinkTracking to update those fields with any changes to those fields.
|
* augmentSyncLinkTracking to update those fields with any changes to those fields.
|
||||||
*
|
*
|
||||||
|
* Note that since both SiteTree and File are versioned, LinkTracking and ImageTracking will
|
||||||
|
* only be enabled for the Stage record.
|
||||||
|
*
|
||||||
|
* {@see SiteTreeFileExtension} for the extension applied to {@see File}
|
||||||
|
*
|
||||||
* @property SiteTree $owner
|
* @property SiteTree $owner
|
||||||
*
|
*
|
||||||
* @property bool $HasBrokenFile
|
* @property bool $HasBrokenFile
|
||||||
@ -19,6 +24,7 @@
|
|||||||
*
|
*
|
||||||
* @method ManyManyList LinkTracking() List of site pages linked on this page.
|
* @method ManyManyList LinkTracking() List of site pages linked on this page.
|
||||||
* @method ManyManyList ImageTracking() List of Images linked on this page.
|
* @method ManyManyList ImageTracking() List of Images linked on this page.
|
||||||
|
* @method ManyManyList BackLinkTracking List of site pages that link to this page.
|
||||||
*/
|
*/
|
||||||
class SiteTreeLinkTracking extends DataExtension {
|
class SiteTreeLinkTracking extends DataExtension {
|
||||||
|
|
||||||
@ -38,6 +44,10 @@ class SiteTreeLinkTracking extends DataExtension {
|
|||||||
"ImageTracking" => "File"
|
"ImageTracking" => "File"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static $belongs_many_many = array(
|
||||||
|
"BackLinkTracking" => "SiteTree.LinkTracking"
|
||||||
|
);
|
||||||
|
|
||||||
private static $many_many_extraFields = array(
|
private static $many_many_extraFields = array(
|
||||||
"LinkTracking" => array("FieldName" => "Varchar"),
|
"LinkTracking" => array("FieldName" => "Varchar"),
|
||||||
"ImageTracking" => array("FieldName" => "Varchar")
|
"ImageTracking" => array("FieldName" => "Varchar")
|
||||||
@ -46,6 +56,8 @@ class SiteTreeLinkTracking extends DataExtension {
|
|||||||
/**
|
/**
|
||||||
* Scrape the content of a field to detect anly links to local SiteTree pages or files
|
* Scrape the content of a field to detect anly links to local SiteTree pages or files
|
||||||
*
|
*
|
||||||
|
* @todo - Replace image tracking with shortcodes
|
||||||
|
*
|
||||||
* @param string $fieldName The name of the field on {@link @owner} to scrape
|
* @param string $fieldName The name of the field on {@link @owner} to scrape
|
||||||
*/
|
*/
|
||||||
public function trackLinksInField($fieldName) {
|
public function trackLinksInField($fieldName) {
|
||||||
@ -151,8 +163,15 @@ class SiteTreeLinkTracking extends DataExtension {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find HTMLText fields on {@link owner} to scrape for links that need tracking
|
* Find HTMLText fields on {@link owner} to scrape for links that need tracking
|
||||||
|
*
|
||||||
|
* @todo Support versioned many_many for per-stage page link tracking
|
||||||
*/
|
*/
|
||||||
public function augmentSyncLinkTracking() {
|
public function augmentSyncLinkTracking() {
|
||||||
|
// Skip live tracking
|
||||||
|
if(\Versioned::current_stage() == \Versioned::get_live_stage()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset boolean broken flags
|
// Reset boolean broken flags
|
||||||
$this->owner->HasBrokenLink = false;
|
$this->owner->HasBrokenLink = false;
|
||||||
$this->owner->HasBrokenFile = false;
|
$this->owner->HasBrokenFile = false;
|
||||||
@ -169,7 +188,9 @@ class SiteTreeLinkTracking extends DataExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($htmlFields as $field) $this->trackLinksInField($field);
|
foreach($htmlFields as $field) {
|
||||||
|
$this->trackLinksInField($field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class VirtualPage extends Page {
|
|||||||
public static $virtualFields;
|
public static $virtualFields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Array Define fields that are not virtual - the virtual page must define these fields themselves.
|
* @var array Define fields that are not virtual - the virtual page must define these fields themselves.
|
||||||
* Note that anything in {@link self::config()->initially_copied_fields} is implicitly included in this list.
|
* Note that anything in {@link self::config()->initially_copied_fields} is implicitly included in this list.
|
||||||
*/
|
*/
|
||||||
private static $non_virtual_fields = array(
|
private static $non_virtual_fields = array(
|
||||||
@ -34,7 +34,7 @@ class VirtualPage extends Page {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Array Define fields that are initially copied to virtual pages but left modifiable after that.
|
* @var array Define fields that are initially copied to virtual pages but left modifiable after that.
|
||||||
*/
|
*/
|
||||||
private static $initially_copied_fields = array(
|
private static $initially_copied_fields = array(
|
||||||
'ShowInMenus',
|
'ShowInMenus',
|
||||||
@ -126,6 +126,7 @@ class VirtualPage extends Page {
|
|||||||
if($this->CopyContentFrom()) {
|
if($this->CopyContentFrom()) {
|
||||||
return $this->CopyContentFrom()->allowedChildren();
|
return $this->CopyContentFrom()->allowedChildren();
|
||||||
}
|
}
|
||||||
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function syncLinkTracking() {
|
public function syncLinkTracking() {
|
||||||
@ -138,19 +139,14 @@ class VirtualPage extends Page {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* We can only publish the page if there is a published source page
|
* We can only publish the page if there is a published source page
|
||||||
|
*
|
||||||
|
* @param Member $member Member to check
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function canPublish($member = null) {
|
public function canPublish($member = null) {
|
||||||
return $this->isPublishable() && parent::canPublish($member);
|
return $this->isPublishable() && parent::canPublish($member);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if we can delete this page from the live site, which is different from can
|
|
||||||
* we publish it.
|
|
||||||
*/
|
|
||||||
public function canDeleteFromLive($member = null) {
|
|
||||||
return parent::canPublish($member);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if is page is publishable by anyone at all
|
* Returns true if is page is publishable by anyone at all
|
||||||
* Return false if the source page isn't published yet.
|
* Return false if the source page isn't published yet.
|
||||||
@ -376,6 +372,9 @@ class VirtualPage extends Page {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure we have an up-to-date version of everything.
|
* Ensure we have an up-to-date version of everything.
|
||||||
|
*
|
||||||
|
* @param DataObject $source
|
||||||
|
* @param bool $updateImageTracking
|
||||||
*/
|
*/
|
||||||
public function copyFrom($source, $updateImageTracking = true) {
|
public function copyFrom($source, $updateImageTracking = true) {
|
||||||
if($source) {
|
if($source) {
|
||||||
|
@ -215,6 +215,7 @@ in the other stage:<br />
|
|||||||
$removedOrphans = array();
|
$removedOrphans = array();
|
||||||
$orphanBaseClass = ClassInfo::baseDataClass($this->orphanedSearchClass);
|
$orphanBaseClass = ClassInfo::baseDataClass($this->orphanedSearchClass);
|
||||||
foreach($orphanIDs as $id) {
|
foreach($orphanIDs as $id) {
|
||||||
|
/** @var SiteTree $stageRecord */
|
||||||
$stageRecord = Versioned::get_one_by_stage(
|
$stageRecord = Versioned::get_one_by_stage(
|
||||||
$this->orphanedSearchClass,
|
$this->orphanedSearchClass,
|
||||||
'Stage',
|
'Stage',
|
||||||
@ -226,6 +227,7 @@ in the other stage:<br />
|
|||||||
$stageRecord->destroy();
|
$stageRecord->destroy();
|
||||||
unset($stageRecord);
|
unset($stageRecord);
|
||||||
}
|
}
|
||||||
|
/** @var SiteTree $liveRecord */
|
||||||
$liveRecord = Versioned::get_one_by_stage(
|
$liveRecord = Versioned::get_one_by_stage(
|
||||||
$this->orphanedSearchClass,
|
$this->orphanedSearchClass,
|
||||||
'Live',
|
'Live',
|
||||||
@ -233,7 +235,7 @@ in the other stage:<br />
|
|||||||
);
|
);
|
||||||
if($liveRecord) {
|
if($liveRecord) {
|
||||||
$removedOrphans[$liveRecord->ID] = sprintf('Removed %s (#%d) from Live', $liveRecord->Title, $liveRecord->ID);
|
$removedOrphans[$liveRecord->ID] = sprintf('Removed %s (#%d) from Live', $liveRecord->Title, $liveRecord->ID);
|
||||||
$liveRecord->doDeleteFromLive();
|
$liveRecord->doUnpublish();
|
||||||
$liveRecord->destroy();
|
$liveRecord->destroy();
|
||||||
unset($liveRecord);
|
unset($liveRecord);
|
||||||
}
|
}
|
||||||
|
58
tests/model/ErrorPageFileExtensionTest.php
Normal file
58
tests/model/ErrorPageFileExtensionTest.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class ErrorPageFileExtensionTest extends SapphireTest {
|
||||||
|
|
||||||
|
protected static $fixture_file = 'ErrorPageTest.yml';
|
||||||
|
|
||||||
|
protected $versionedMode = null;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
$this->versionedMode = Versioned::get_reading_mode();
|
||||||
|
Versioned::reading_stage('Stage');
|
||||||
|
AssetStoreTest_SpyStore::activate('ErrorPageFileExtensionTest');
|
||||||
|
$file = new File();
|
||||||
|
$file->setFromString('dummy', 'dummy.txt');
|
||||||
|
$file->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
Versioned::set_reading_mode($this->versionedMode);
|
||||||
|
AssetStoreTest_SpyStore::reset();
|
||||||
|
parent::tearDown(); // TODO: Change the autogenerated stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testErrorPage() {
|
||||||
|
// Get and publish records
|
||||||
|
$notFoundPage = $this->objFromFixture('ErrorPage', '404');
|
||||||
|
$notFoundPage->publish('Stage', 'Live');
|
||||||
|
$notFoundLink = $notFoundPage->Link();
|
||||||
|
|
||||||
|
$disallowedPage = $this->objFromFixture('ErrorPage', '403');
|
||||||
|
$disallowedPage->publish('Stage', 'Live');
|
||||||
|
$disallowedLink = $disallowedPage->Link();
|
||||||
|
|
||||||
|
// Get stage version of file
|
||||||
|
$file = File::get()->first();
|
||||||
|
$fileLink = $file->Link();
|
||||||
|
Session::clear("loggedInAs");
|
||||||
|
|
||||||
|
// Generate shortcode for a file which doesn't exist
|
||||||
|
$shortcode = File::handle_shortcode(array('id' => 9999), null, new ShortcodeParser(), 'file_link');
|
||||||
|
$this->assertEquals($notFoundLink, $shortcode);
|
||||||
|
$shortcode = File::handle_shortcode(array('id' => 9999), 'click here', new ShortcodeParser(), 'file_link');
|
||||||
|
$this->assertEquals(sprintf('<a href="%s">%s</a>', $notFoundLink, 'click here'), $shortcode);
|
||||||
|
|
||||||
|
// Test that user cannot view draft file
|
||||||
|
$shortcode = File::handle_shortcode(array('id' => $file->ID), null, new ShortcodeParser(), 'file_link');
|
||||||
|
$this->assertEquals($disallowedLink, $shortcode);
|
||||||
|
$shortcode = File::handle_shortcode(array('id' => $file->ID), 'click here', new ShortcodeParser(), 'file_link');
|
||||||
|
$this->assertEquals(sprintf('<a href="%s">%s</a>', $disallowedLink, 'click here'), $shortcode);
|
||||||
|
|
||||||
|
// Authenticated users don't get the same error
|
||||||
|
$this->logInWithPermission('ADMIN');
|
||||||
|
$shortcode = File::handle_shortcode(array('id' => $file->ID), null, new ShortcodeParser(), 'file_link');
|
||||||
|
$this->assertEquals($fileLink, $shortcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
ErrorPage:
|
ErrorPage:
|
||||||
404:
|
404:
|
||||||
Title: Page Not Found
|
Title: Page Not Found
|
||||||
URLSegment: page-not-found
|
URLSegment: page-not-found
|
||||||
Content: My error page body
|
Content: My error page body
|
||||||
ErrorCode: 404
|
ErrorCode: 404
|
||||||
403:
|
403:
|
||||||
Title: Permission Failure
|
Title: Permission Failure
|
||||||
URLSegment: permission-denied
|
URLSegment: permission-denied
|
||||||
Content: You do not have permission to view this page
|
Content: You do not have permission to view this page
|
||||||
ErrorCode: 403
|
ErrorCode: 403
|
||||||
|
@ -8,6 +8,9 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
|
|
||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
|
Versioned::reading_stage('Stage');
|
||||||
|
|
||||||
AssetStoreTest_SpyStore::activate('FileLinkTrackingTest');
|
AssetStoreTest_SpyStore::activate('FileLinkTrackingTest');
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
|
|
||||||
@ -17,6 +20,8 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
$destPath = AssetStoreTest_SpyStore::getLocalPath($file);
|
$destPath = AssetStoreTest_SpyStore::getLocalPath($file);
|
||||||
Filesystem::makeFolder(dirname($destPath));
|
Filesystem::makeFolder(dirname($destPath));
|
||||||
file_put_contents($destPath, str_repeat('x', 1000000));
|
file_put_contents($destPath, str_repeat('x', 1000000));
|
||||||
|
// Ensure files are published, thus have public urls
|
||||||
|
$file->doPublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we can't hard-code IDs, manually inject image tracking shortcode
|
// Since we can't hard-code IDs, manually inject image tracking shortcode
|
||||||
@ -36,7 +41,13 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
|
|
||||||
public function testFileRenameUpdatesDraftAndPublishedPages() {
|
public function testFileRenameUpdatesDraftAndPublishedPages() {
|
||||||
$page = $this->objFromFixture('Page', 'page1');
|
$page = $this->objFromFixture('Page', 'page1');
|
||||||
$this->assertTrue($page->doPublish());
|
$page->doPublish();
|
||||||
|
|
||||||
|
// Live and stage pages both have link to public file
|
||||||
|
$this->assertContains(
|
||||||
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/testscript-test-file.jpg"',
|
||||||
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
);
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/testscript-test-file.jpg"',
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/testscript-test-file.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
@ -46,6 +57,34 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
$file->Name = 'renamed-test-file.jpg';
|
$file->Name = 'renamed-test-file.jpg';
|
||||||
$file->write();
|
$file->write();
|
||||||
|
|
||||||
|
// Staged record now points to secure URL of renamed file, live record remains unchanged
|
||||||
|
// Note that the "secure" url doesn't have the "FileLinkTrackingTest" component because
|
||||||
|
// the mocked test location disappears for secure files.
|
||||||
|
$this->assertContains(
|
||||||
|
'<img src="/assets/55b443b601/renamed-test-file.jpg"',
|
||||||
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
);
|
||||||
|
$this->assertContains(
|
||||||
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/testscript-test-file.jpg"',
|
||||||
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Publishing the file should result in a direct public link (indicated by "FileLinkTrackingTest")
|
||||||
|
// Although the old live page will still point to the old record.
|
||||||
|
// @todo - Ensure shortcodes are used with all images to prevent live records having broken links
|
||||||
|
$file->doPublish();
|
||||||
|
$this->assertContains(
|
||||||
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
||||||
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
);
|
||||||
|
$this->assertContains(
|
||||||
|
// Note: Broken link until shortcode-enabled
|
||||||
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/testscript-test-file.jpg"',
|
||||||
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Publishing the page after publishing the asset will resolve any link issues
|
||||||
|
$page->doPublish();
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
@ -72,11 +111,16 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
$file->Name = 'renamed-test-file.jpg';
|
$file->Name = 'renamed-test-file.jpg';
|
||||||
$file->write();
|
$file->write();
|
||||||
|
|
||||||
// Verify that the draft and publish virtual pages both have the corrected link
|
// Verify that the draft virtual pages have the correct content
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
'<img src="/assets/55b443b601/renamed-test-file.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($svp->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($svp->ID))->value()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Publishing both file and page will update the live record
|
||||||
|
$file->doPublish();
|
||||||
|
$page->doPublish();
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($svp->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($svp->ID))->value()
|
||||||
@ -119,12 +163,16 @@ class FileLinkTrackingTest extends SapphireTest {
|
|||||||
$file = DataObject::get_by_id('File', $file->ID);
|
$file = DataObject::get_by_id('File', $file->ID);
|
||||||
$file->Name = 'renamed-test-file-second-time.jpg';
|
$file->Name = 'renamed-test-file-second-time.jpg';
|
||||||
$file->write();
|
$file->write();
|
||||||
|
$file->doPublish();
|
||||||
|
|
||||||
// Confirm that the correct image is shown in both the draft and live site
|
// Confirm that the correct image is shown in both the draft and live site
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file-second-time.jpg"',
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file-second-time.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Publishing this record also updates live record
|
||||||
|
$page->doPublish();
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file-second-time.jpg"',
|
'<img src="/assets/FileLinkTrackingTest/55b443b601/renamed-test-file-second-time.jpg"',
|
||||||
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
DB::prepared_query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = ?", array($page->ID))->value()
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@see SiteTreeLinkTracking} broken links feature: LinkTracking
|
||||||
|
*/
|
||||||
class SiteTreeBacklinksTest extends SapphireTest {
|
class SiteTreeBacklinksTest extends SapphireTest {
|
||||||
protected static $fixture_file = "SiteTreeBacklinksTest.yml";
|
protected static $fixture_file = "SiteTreeBacklinksTest.yml";
|
||||||
|
|
||||||
@ -78,6 +81,8 @@ class SiteTreeBacklinksTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testChangingUrlOnLiveSiteRewritesLink() {
|
public function testChangingUrlOnLiveSiteRewritesLink() {
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
|
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
@ -109,6 +114,8 @@ class SiteTreeBacklinksTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testPublishingPageWithModifiedUrlRewritesLink() {
|
public function testPublishingPageWithModifiedUrlRewritesLink() {
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
|
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
@ -144,6 +151,8 @@ class SiteTreeBacklinksTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testPublishingPageWithModifiedLinksRewritesLinks() {
|
public function testPublishingPageWithModifiedLinksRewritesLinks() {
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
|
|
||||||
// publish page 1 & 3
|
// publish page 1 & 3
|
||||||
$page1 = $this->objFromFixture('Page', 'page1');
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
$page3 = $this->objFromFixture('Page', 'page3');
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
@ -209,6 +218,9 @@ class SiteTreeBacklinksTest extends SapphireTest {
|
|||||||
$page2 = $this->objFromFixture('Page', 'page2');
|
$page2 = $this->objFromFixture('Page', '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());
|
||||||
|
|
||||||
|
// @todo - Implement versioned many_many
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
|
|
||||||
// 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("Page", "Live", "\"SiteTree\".\"ID\" = $page2->ID");
|
||||||
Versioned::reading_stage('Live');
|
Versioned::reading_stage('Live');
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
|
* Tests {@see SiteTreeLinkTracking} broken links feature: LinkTracking
|
||||||
|
*
|
||||||
* @package cms
|
* @package cms
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class SiteTreeBrokenLinksTest extends SapphireTest {
|
class SiteTreeBrokenLinksTest extends SapphireTest {
|
||||||
protected static $fixture_file = 'SiteTreeBrokenLinksTest.yml';
|
protected static $fixture_file = 'SiteTreeBrokenLinksTest.yml';
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
Versioned::reading_stage('Stage');
|
||||||
|
AssetStoreTest_SpyStore::activate('SiteTreeBrokenLinksTest');
|
||||||
|
$this->logInWithPermission('ADMIN');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown() {
|
||||||
|
AssetStoreTest_SpyStore::reset();
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public function testBrokenLinksBetweenPages() {
|
public function testBrokenLinksBetweenPages() {
|
||||||
$obj = $this->objFromFixture('Page','content');
|
$obj = $this->objFromFixture('Page','content');
|
||||||
|
|
||||||
@ -62,7 +77,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest {
|
|||||||
public function testDeletingFileMarksBackedPagesAsBroken() {
|
public function testDeletingFileMarksBackedPagesAsBroken() {
|
||||||
// Test entry
|
// Test entry
|
||||||
$file = new File();
|
$file = new File();
|
||||||
$file->Filename = 'test-file.pdf';
|
$file->setFromString('test', 'test-file.txt');
|
||||||
$file->write();
|
$file->write();
|
||||||
|
|
||||||
$obj = $this->objFromFixture('Page','content');
|
$obj = $this->objFromFixture('Page','content');
|
||||||
@ -83,65 +98,48 @@ class SiteTreeBrokenLinksTest extends SapphireTest {
|
|||||||
// Delete the file
|
// Delete the file
|
||||||
$file->delete();
|
$file->delete();
|
||||||
|
|
||||||
// Confirm that it is marked as broken in both stage and live
|
// Confirm that it is marked as broken in stage
|
||||||
$obj->flushCache();
|
$obj->flushCache();
|
||||||
$obj = DataObject::get_by_id("SiteTree", $obj->ID);
|
$obj = DataObject::get_by_id("SiteTree", $obj->ID);
|
||||||
$this->assertEquals(1, $obj->HasBrokenFile);
|
$this->assertEquals(1, $obj->HasBrokenFile);
|
||||||
|
|
||||||
|
// Publishing this page marks it as broken on live too
|
||||||
|
$obj->doPublish();
|
||||||
$liveObj = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $obj->ID");
|
$liveObj = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $obj->ID");
|
||||||
$this->assertEquals(1, $liveObj->HasBrokenFile);
|
$this->assertEquals(1, $liveObj->HasBrokenFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDeletingMarksBackLinkedPagesAsBroken() {
|
public function testDeletingMarksBackLinkedPagesAsBroken() {
|
||||||
$this->logInWithPermission('ADMIN');
|
|
||||||
|
|
||||||
// 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('Page','about');
|
||||||
$linkDest->doPublish();
|
|
||||||
|
|
||||||
$linkSrc = $this->objFromFixture('Page','content');
|
$linkSrc = $this->objFromFixture('Page','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();
|
||||||
|
|
||||||
$linkSrc->doPublish();
|
|
||||||
|
|
||||||
// Confirm no broken link
|
// Confirm no broken link
|
||||||
$this->assertEquals(0, (int)$linkSrc->HasBrokenLink);
|
$this->assertEquals(0, (int)$linkSrc->HasBrokenLink);
|
||||||
$this->assertEquals(0, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
|
||||||
WHERE \"ID\" = $linkSrc->ID")->value());
|
|
||||||
|
|
||||||
// Delete page from draft
|
// Delete page from draft
|
||||||
$linkDestID = $linkDest->ID;
|
$linkDestID = $linkDest->ID;
|
||||||
$linkDest->delete();
|
$linkDest->delete();
|
||||||
|
|
||||||
// Confirm draft has broken link, and published doesn't
|
// Confirm draft has broken link
|
||||||
$linkSrc->flushCache();
|
$linkSrc->flushCache();
|
||||||
$linkSrc = $this->objFromFixture('Page', 'content');
|
$linkSrc = $this->objFromFixture('Page', 'content');
|
||||||
|
|
||||||
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
||||||
$this->assertEquals(0, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
|
||||||
WHERE \"ID\" = $linkSrc->ID")->value());
|
|
||||||
|
|
||||||
// Delete from live
|
|
||||||
$linkDest = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $linkDestID");
|
|
||||||
$linkDest->doDeleteFromLive();
|
|
||||||
|
|
||||||
// Confirm both draft and published have broken link
|
|
||||||
$linkSrc->flushCache();
|
|
||||||
$linkSrc = $this->objFromFixture('Page', 'content');
|
|
||||||
|
|
||||||
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
|
||||||
$this->assertEquals(1, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
|
||||||
WHERE \"ID\" = $linkSrc->ID")->value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testPublishingSourceBeforeDestHasBrokenLink() {
|
public function testPublishingSourceBeforeDestHasBrokenLink() {
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
|
|
||||||
$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
|
||||||
$linkDest = $this->objFromFixture('Page','about');
|
$linkDest = $this->objFromFixture('Page','about');
|
||||||
// Ensure that it's not on the published site
|
// Ensure that it's not on the published site
|
||||||
$linkDest->doDeleteFromLive();
|
$linkDest->doUnpublish();
|
||||||
|
|
||||||
$linkSrc = $this->objFromFixture('Page','content');
|
$linkSrc = $this->objFromFixture('Page','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>";
|
||||||
@ -157,6 +155,7 @@ class SiteTreeBrokenLinksTest extends SapphireTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testRestoreFixesBrokenLinks() {
|
public function testRestoreFixesBrokenLinks() {
|
||||||
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
||||||
// Create page and virtual page
|
// Create page and virtual page
|
||||||
$p = new Page();
|
$p = new Page();
|
||||||
$p->Title = "source";
|
$p->Title = "source";
|
||||||
|
@ -1,27 +1,21 @@
|
|||||||
Page:
|
Page:
|
||||||
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>.'
|
||||||
about:
|
about:
|
||||||
Title: About
|
Title: About
|
||||||
URLSegment: about
|
URLSegment: about
|
||||||
Content: 'about us here <a name="yes-anchor-here">about skiplinks here</a>.'
|
Content: 'about us here <a name="yes-anchor-here">about skiplinks here</a>.'
|
||||||
brokenInternalRedirector:
|
brokenInternalRedirector:
|
||||||
RedirectionType: Internal
|
RedirectionType: Internal
|
||||||
Title: RedirectorPageToBrokenInteralPage
|
Title: RedirectorPageToBrokenInteralPage
|
||||||
LinkToID: 0
|
LinkToID: 0
|
||||||
workingInternalRedirector:
|
workingInternalRedirector:
|
||||||
RedirectionType: Internal
|
RedirectionType: Internal
|
||||||
Title: RedirectorPageToBrokenInteralPage
|
Title: RedirectorPageToBrokenInteralPage
|
||||||
LinkTo: =>Page.content
|
LinkTo: =>Page.content
|
||||||
|
|
||||||
File:
|
|
||||||
privacypolicy:
|
|
||||||
Name: privacypolicy.pdf
|
|
||||||
Title: privacypolicy.pdf
|
|
||||||
Filename: assets/privacypolicy.pdf
|
|
||||||
|
|
||||||
ErrorPage:
|
ErrorPage:
|
||||||
404:
|
404:
|
||||||
Title: Page not Found
|
Title: Page not Found
|
||||||
ErrorCode: 404
|
ErrorCode: 404
|
||||||
|
@ -381,7 +381,7 @@ class SiteTreeTest extends SapphireTest {
|
|||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'about');
|
$parentPage = $this->objFromFixture('Page', 'about');
|
||||||
|
|
||||||
$parentPage->doDeleteFromLive();
|
$parentPage->doUnpublish();
|
||||||
|
|
||||||
Versioned::reading_stage('Live');
|
Versioned::reading_stage('Live');
|
||||||
|
|
||||||
@ -425,7 +425,7 @@ class SiteTreeTest extends SapphireTest {
|
|||||||
$pageStaffDuplicate->doPublish();
|
$pageStaffDuplicate->doPublish();
|
||||||
|
|
||||||
$parentPage = $this->objFromFixture('Page', 'about');
|
$parentPage = $this->objFromFixture('Page', 'about');
|
||||||
$parentPage->doDeleteFromLive();
|
$parentPage->doUnpublish();
|
||||||
|
|
||||||
Versioned::reading_stage('Live');
|
Versioned::reading_stage('Live');
|
||||||
$this->assertFalse(DataObject::get_by_id('Page', $pageAbout->ID));
|
$this->assertFalse(DataObject::get_by_id('Page', $pageAbout->ID));
|
||||||
|
@ -198,14 +198,14 @@ class VirtualPageTest extends FunctionalTest {
|
|||||||
|
|
||||||
// Delete the source page
|
// Delete the source page
|
||||||
$this->assertTrue($vp->canPublish());
|
$this->assertTrue($vp->canPublish());
|
||||||
$this->assertTrue($p->doDeleteFromLive());
|
$this->assertTrue($p->doUnpublish());
|
||||||
|
|
||||||
// Confirm that we can unpublish, but not publish
|
// Confirm that we can unpublish, but not publish
|
||||||
$this->assertTrue($vp->canDeleteFromLive());
|
$this->assertTrue($vp->canUnpublish());
|
||||||
$this->assertFalse($vp->canPublish());
|
$this->assertFalse($vp->canPublish());
|
||||||
|
|
||||||
// Confirm that the action really works
|
// Confirm that the action really works
|
||||||
$this->assertTrue($vp->doDeleteFromLive());
|
$this->assertTrue($vp->doUnpublish());
|
||||||
$this->assertNull(DB::query("SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"ID\" = $vp->ID")->value());
|
$this->assertNull(DB::query("SELECT \"ID\" FROM \"SiteTree_Live\" WHERE \"ID\" = $vp->ID")->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ class VirtualPageTest extends FunctionalTest {
|
|||||||
|
|
||||||
// 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
|
||||||
$pLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $pID);
|
$pLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $pID);
|
||||||
$this->assertTrue($pLive->doDeleteFromLive());
|
$this->assertTrue($pLive->doUnpublish());
|
||||||
$vpLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $vp->ID);
|
$vpLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $vp->ID);
|
||||||
$this->assertNull($vpLive);
|
$this->assertNull($vpLive);
|
||||||
|
|
||||||
|
@ -225,7 +225,10 @@ class ZZZSearchFormTest extends FunctionalTest {
|
|||||||
$sf = new SearchForm($this->mockController, 'SearchForm');
|
$sf = new SearchForm($this->mockController, 'SearchForm');
|
||||||
|
|
||||||
$dontShowInSearchFile = $this->objFromFixture('File', 'dontShowInSearchFile');
|
$dontShowInSearchFile = $this->objFromFixture('File', 'dontShowInSearchFile');
|
||||||
|
$dontShowInSearchFile->publish('Stage', 'Live');
|
||||||
$showInSearchFile = $this->objFromFixture('File', 'showInSearchFile');
|
$showInSearchFile = $this->objFromFixture('File', 'showInSearchFile');
|
||||||
|
$showInSearchFile->publish('Stage', 'Live');
|
||||||
|
|
||||||
$results = $sf->getResults(null, array('Search'=>'dontShowInSearchFile'));
|
$results = $sf->getResults(null, array('Search'=>'dontShowInSearchFile'));
|
||||||
$this->assertNotContains(
|
$this->assertNotContains(
|
||||||
$dontShowInSearchFile->ID,
|
$dontShowInSearchFile->ID,
|
||||||
|
@ -1,43 +1,43 @@
|
|||||||
Group:
|
Group:
|
||||||
websiteusers:
|
websiteusers:
|
||||||
Title: View certain restricted pages
|
Title: View certain restricted pages
|
||||||
Member:
|
Member:
|
||||||
randomuser:
|
randomuser:
|
||||||
Email: randomuser@test.com
|
Email: randomuser@test.com
|
||||||
Password: test
|
Password: test
|
||||||
websiteuser:
|
websiteuser:
|
||||||
Email: websiteuser@test.com
|
Email: websiteuser@test.com
|
||||||
Password: test
|
Password: test
|
||||||
Groups: =>Group.websiteusers
|
Groups: =>Group.websiteusers
|
||||||
SiteTree:
|
SiteTree:
|
||||||
searchformholder:
|
searchformholder:
|
||||||
URLSegment: searchformholder
|
URLSegment: searchformholder
|
||||||
Title: searchformholder
|
Title: searchformholder
|
||||||
publicPublishedPage:
|
publicPublishedPage:
|
||||||
Title: publicPublishedPage
|
Title: publicPublishedPage
|
||||||
publicUnpublishedPage:
|
publicUnpublishedPage:
|
||||||
Title: publicUnpublishedPage
|
Title: publicUnpublishedPage
|
||||||
restrictedViewLoggedInUsers:
|
restrictedViewLoggedInUsers:
|
||||||
CanViewType: LoggedInUsers
|
CanViewType: LoggedInUsers
|
||||||
Title: restrictedViewLoggedInUsers
|
Title: restrictedViewLoggedInUsers
|
||||||
restrictedViewOnlyWebsiteUsers:
|
restrictedViewOnlyWebsiteUsers:
|
||||||
CanViewType: OnlyTheseUsers
|
CanViewType: OnlyTheseUsers
|
||||||
ViewerGroups: =>Group.websiteusers
|
ViewerGroups: =>Group.websiteusers
|
||||||
Title: restrictedViewOnlyWebsiteUsers
|
Title: restrictedViewOnlyWebsiteUsers
|
||||||
inheritRestrictedView:
|
inheritRestrictedView:
|
||||||
CanViewType: Inherit
|
CanViewType: Inherit
|
||||||
Parent: =>SiteTree.restrictedViewLoggedInUsers
|
Parent: =>SiteTree.restrictedViewLoggedInUsers
|
||||||
Title: inheritRestrictedView
|
Title: inheritRestrictedView
|
||||||
dontShowInSearchPage:
|
dontShowInSearchPage:
|
||||||
Title: dontShowInSearchPage
|
Title: dontShowInSearchPage
|
||||||
ShowInSearch: 0
|
ShowInSearch: 0
|
||||||
pageWithSpecialChars:
|
pageWithSpecialChars:
|
||||||
Title: Brötchen
|
Title: Brötchen
|
||||||
Content: Frisch vom Bäcker
|
Content: Frisch vom Bäcker
|
||||||
File:
|
File:
|
||||||
showInSearchFile:
|
showInSearchFile:
|
||||||
Title: showInSearchFile
|
Title: showInSearchFile
|
||||||
ShowInSearch: 1
|
ShowInSearch: 1
|
||||||
dontShowInSearchFile:
|
dontShowInSearchFile:
|
||||||
Title: dontShowInSearchFile
|
Title: dontShowInSearchFile
|
||||||
ShowInSearch: 0
|
ShowInSearch: 0
|
||||||
|
Loading…
Reference in New Issue
Block a user