mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 06:05:56 +00:00
Merge remote-tracking branch 'origin/3.1'
Conflicts: .travis.yml
This commit is contained in:
commit
b3699281c0
@ -26,6 +26,9 @@ matrix:
|
||||
env: DB=MYSQL CORE_RELEASE=master
|
||||
- php: 5.4
|
||||
env: DB=MYSQL CORE_RELEASE=master BEHAT_TEST=1
|
||||
allow_failures:
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=master
|
||||
|
||||
before_script:
|
||||
- composer self-update
|
||||
@ -38,7 +41,7 @@ before_script:
|
||||
- php ~/travis-support/travis_setup_php54_webserver.php --if-env BEHAT_TEST
|
||||
|
||||
script:
|
||||
- "if [ \"$BEHAT_TEST\" = \"\" ]; then phpunit cms/tests; fi"
|
||||
- "if [ \"$BEHAT_TEST\" = \"\" ]; then vendor/bin/phpunit cms/tests; fi"
|
||||
- "if [ \"$BEHAT_TEST\" = \"1\" ]; then vendor/bin/behat @cms; fi"
|
||||
|
||||
after_failure:
|
||||
|
@ -16,6 +16,14 @@ class AssetAdmin extends LeftAndMain implements PermissionProvider{
|
||||
|
||||
private static $tree_class = 'Folder';
|
||||
|
||||
/**
|
||||
* Amount of results showing on a single page.
|
||||
*
|
||||
* @config
|
||||
* @var int
|
||||
*/
|
||||
private static $page_length = 15;
|
||||
|
||||
/**
|
||||
* @config
|
||||
* @see Upload->allowedMaxFileSize
|
||||
@ -98,17 +106,19 @@ JS
|
||||
// Don't filter list when a detail view is requested,
|
||||
// to avoid edge cases where the filtered list wouldn't contain the requested
|
||||
// record due to faulty session state (current folder not always encoded in URL, see #7408).
|
||||
if(!$folder->ID && $this->request->requestVar('ID') === null && ($this->request->param('ID') == 'field')) {
|
||||
if(!$folder->ID
|
||||
&& $this->request->requestVar('ID') === null
|
||||
&& ($this->request->param('ID') == 'field')
|
||||
) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
// Re-add previously removed "Name" filter as combined filter
|
||||
// TODO Replace with composite SearchFilter once that API exists
|
||||
if(isset($params['Name'])) {
|
||||
$list = $list->where(sprintf(
|
||||
'"Name" LIKE \'%%%s%%\' OR "Title" LIKE \'%%%s%%\'',
|
||||
Convert::raw2sql($params['Name']),
|
||||
Convert::raw2sql($params['Name'])
|
||||
if(!empty($params['Name'])) {
|
||||
$list = $list->filterAny(array(
|
||||
'Name:PartialMatch' => $params['Name'],
|
||||
'Title:PartialMatch' => $params['Name']
|
||||
));
|
||||
}
|
||||
|
||||
@ -117,23 +127,26 @@ JS
|
||||
|
||||
// If a search is conducted, check for the "current folder" limitation.
|
||||
// Otherwise limit by the current folder as denoted by the URL.
|
||||
if(!$params || @$params['CurrentFolderOnly']) {
|
||||
if(empty($params) || !empty($params['CurrentFolderOnly'])) {
|
||||
$list = $list->filter('ParentID', $folder->ID);
|
||||
}
|
||||
|
||||
// Category filter
|
||||
if(isset($params['AppCategory'])) {
|
||||
if(isset(File::config()->app_categories[$params['AppCategory']])) {
|
||||
$exts = File::config()->app_categories[$params['AppCategory']];
|
||||
} else {
|
||||
$exts = array();
|
||||
}
|
||||
$categorySQLs = array();
|
||||
foreach($exts as $ext) $categorySQLs[] = '"File"."Name" LIKE \'%.' . $ext . '\'';
|
||||
// TODO Use DataList->filterAny() once OR connectives are implemented properly
|
||||
if (count($categorySQLs) > 0) {
|
||||
$list = $list->where('(' . implode(' OR ', $categorySQLs) . ')');
|
||||
}
|
||||
if(!empty($params['AppCategory'])
|
||||
&& !empty(File::config()->app_categories[$params['AppCategory']])
|
||||
) {
|
||||
$exts = File::config()->app_categories[$params['AppCategory']];
|
||||
$list = $list->filter('Name:PartialMatch', $exts);
|
||||
}
|
||||
|
||||
// Date filter
|
||||
if(!empty($params['CreatedFrom'])) {
|
||||
$fromDate = new DateField(null, null, $params['CreatedFrom']);
|
||||
$list = $list->filter("Created:GreaterThanOrEqual", $fromDate->dataValue());
|
||||
}
|
||||
if(!empty($params['CreatedTo'])) {
|
||||
$toDate = new DateField(null, null, $params['CreatedTo']);
|
||||
$list = $list->filter("Created:LessThanOrEqual", $toDate->dataValue());
|
||||
}
|
||||
|
||||
return $list;
|
||||
@ -150,9 +163,9 @@ JS
|
||||
$gridFieldConfig = GridFieldConfig::create()->addComponents(
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldSortableHeader(),
|
||||
new GridFieldFilterHeader(),
|
||||
new GridFieldFilterHeader(),
|
||||
new GridFieldDataColumns(),
|
||||
new GridFieldPaginator(15),
|
||||
new GridFieldPaginator(self::config()->page_length),
|
||||
new GridFieldEditButton(),
|
||||
new GridFieldDeleteAction(),
|
||||
new GridFieldDetailForm(),
|
||||
@ -342,6 +355,21 @@ JS
|
||||
foreach($context->getFilters() as $filter) $filter->setFullName(sprintf('q[%s]', $filter->getFullName()));
|
||||
|
||||
// Customize fields
|
||||
$context->addField(
|
||||
new HeaderField('q[Date]', _t('CMSSearch.FILTERDATEHEADING', 'Date'), 4)
|
||||
);
|
||||
$context->addField(
|
||||
DateField::create(
|
||||
'q[CreatedFrom]',
|
||||
_t('CMSSearch.FILTERDATEFROM', 'From')
|
||||
)->setConfig('showcalendar', true)
|
||||
);
|
||||
$context->addField(
|
||||
DateField::create(
|
||||
'q[CreatedTo]',
|
||||
_t('CMSSearch.FILTERDATETO', 'To')
|
||||
)->setConfig('showcalendar', true)
|
||||
);
|
||||
$appCategories = array(
|
||||
'image' => _t('AssetAdmin.AppCategoryImage', 'Image'),
|
||||
'audio' => _t('AssetAdmin.AppCategoryAudio', 'Audio'),
|
||||
@ -382,7 +410,7 @@ JS
|
||||
$fields = $context->getSearchFields();
|
||||
$actions = new FieldList(
|
||||
FormAction::create('doSearch', _t('CMSMain_left_ss.APPLY_FILTER', 'Apply Filter'))
|
||||
->addExtraClass('ss-ui-action-constructive'),
|
||||
->addExtraClass('ss-ui-action-constructive'),
|
||||
Object::create('ResetFormAction', 'clear', _t('CMSMain_left_ss.RESET', 'Reset'))
|
||||
);
|
||||
|
||||
|
@ -27,6 +27,14 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
||||
|
||||
private static $subitem_class = "Member";
|
||||
|
||||
/**
|
||||
* Amount of results showing on a single page.
|
||||
*
|
||||
* @config
|
||||
* @var int
|
||||
*/
|
||||
private static $page_length = 15;
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'buildbrokenlinks',
|
||||
'deleteitems',
|
||||
@ -726,7 +734,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
|
||||
$gridFieldConfig = GridFieldConfig::create()->addComponents(
|
||||
new GridFieldSortableHeader(),
|
||||
new GridFieldDataColumns(),
|
||||
new GridFieldPaginator(15)
|
||||
new GridFieldPaginator(self::config()->page_length)
|
||||
);
|
||||
if($parentID){
|
||||
$gridFieldConfig->addComponent(
|
||||
|
@ -4,10 +4,10 @@
|
||||
*
|
||||
* The simplest way of building a CMSSiteTreeFilter is to create a pagesToBeShown() method that
|
||||
* returns an Iterator of maps, each entry containing the 'ID' and 'ParentID' of the pages to be
|
||||
* included in the tree. The reuslt of a DB::query() can be returned directly.
|
||||
* included in the tree. The result of a DB::query() can then be returned directly.
|
||||
*
|
||||
* If you wish to make a more complex tree, you can overload includeInTree($page) to return true/
|
||||
* false depending on whether the given page should be included. Note that you will need to include
|
||||
* false depending on whether the given page should be included. Note that you will need to include
|
||||
* parent helper pages yourself.
|
||||
*
|
||||
* @package cms
|
||||
@ -44,18 +44,22 @@ abstract class CMSSiteTreeFilter extends Object {
|
||||
public static function get_all_filters() {
|
||||
// get all filter instances
|
||||
$filters = ClassInfo::subclassesFor('CMSSiteTreeFilter');
|
||||
|
||||
// remove abstract CMSSiteTreeFilter class
|
||||
array_shift($filters);
|
||||
|
||||
// add filters to map
|
||||
$filterMap = array();
|
||||
|
||||
foreach($filters as $filter) {
|
||||
$filterMap[$filter] = call_user_func(array($filter, 'title'));
|
||||
$filterMap[$filter] = $filter::title();
|
||||
}
|
||||
// ensure that 'all pages' filter is on top position
|
||||
uasort($filterMap,
|
||||
create_function('$a,$b', 'return ($a == "CMSSiteTreeFilter_Search") ? 1 : -1;')
|
||||
);
|
||||
|
||||
// Ensure that 'all pages' filter is on top position and everything else is sorted alphabetically
|
||||
uasort($filterMap, function($a, $b) {
|
||||
return ($a === CMSSiteTreeFilter_Search::title())
|
||||
? -1
|
||||
: strcasecmp($a, $b);
|
||||
});
|
||||
|
||||
return $filterMap;
|
||||
}
|
||||
@ -125,7 +129,68 @@ abstract class CMSSiteTreeFilter extends Object {
|
||||
|
||||
return (isset($this->_cache_ids[$page->ID]) && $this->_cache_ids[$page->ID]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the default filters to a specified DataList of pages
|
||||
*
|
||||
* @param DataList $query Unfiltered query
|
||||
* @return DataList Filtered query
|
||||
*/
|
||||
protected function applyDefaultFilters($query) {
|
||||
$sng = singleton('SiteTree');
|
||||
foreach($this->params as $name => $val) {
|
||||
if(empty($val)) continue;
|
||||
|
||||
switch($name) {
|
||||
case 'Term':
|
||||
$query = $query->filterAny(array(
|
||||
'URLSegment:PartialMatch' => $val,
|
||||
'Title:PartialMatch' => $val,
|
||||
'MenuTitle:PartialMatch' => $val,
|
||||
'Content:PartialMatch' => $val
|
||||
));
|
||||
break;
|
||||
|
||||
case 'LastEditedFrom':
|
||||
$fromDate = new DateField(null, null, $val);
|
||||
$query = $query->filter("LastEdited:GreaterThanOrEqual", $fromDate->dataValue());
|
||||
break;
|
||||
|
||||
case 'LastEditedTo':
|
||||
$toDate = new DateField(null, null, $val);
|
||||
$query = $query->filter("LastEdited:LessThanOrEqual", $toDate->dataValue());
|
||||
break;
|
||||
|
||||
case 'ClassName':
|
||||
if($val != 'All') {
|
||||
$query = $query->filter('ClassName', $val);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if($sng->hasDatabaseField($name)) {
|
||||
$filter = $sng->dbObject($name)->defaultSearchFilter();
|
||||
$filter->setValue($val);
|
||||
$query = $query->alterDataQuery(array($filter, 'apply'));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a list of pages to an array of associative arrays with ID and ParentID keys
|
||||
*
|
||||
* @param DataList $pages
|
||||
* @return array
|
||||
*/
|
||||
protected function mapIDs($pages) {
|
||||
$ids = array();
|
||||
if($pages) foreach($pages as $page) {
|
||||
$ids[] = array('ID' => $page->ID, 'ParentID' => $page->ParentID);
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,13 +210,9 @@ class CMSSiteTreeFilter_DeletedPages extends CMSSiteTreeFilter {
|
||||
}
|
||||
|
||||
public function pagesIncluded() {
|
||||
$ids = array();
|
||||
// TODO Not very memory efficient, but usually not very many deleted pages exist
|
||||
$pages = Versioned::get_including_deleted('SiteTree');
|
||||
if($pages) foreach($pages as $page) {
|
||||
$ids[] = array('ID' => $page->ID, 'ParentID' => $page->ParentID);
|
||||
}
|
||||
return $ids;
|
||||
$pages = $this->applyDefaultFilters($pages);
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,18 +229,100 @@ class CMSSiteTreeFilter_ChangedPages extends CMSSiteTreeFilter {
|
||||
}
|
||||
|
||||
public function pagesIncluded() {
|
||||
$ids = array();
|
||||
$q = new SQLQuery();
|
||||
$q->setSelect(array('"SiteTree"."ID"','"SiteTree"."ParentID"'))
|
||||
->setFrom('"SiteTree"')
|
||||
->addLeftJoin('SiteTree_Live', '"SiteTree_Live"."ID" = "SiteTree"."ID"')
|
||||
->setWhere('"SiteTree"."Version" > "SiteTree_Live"."Version"');
|
||||
$pages = Versioned::get_by_stage('SiteTree', 'Stage');
|
||||
$pages = $this->applyDefaultFilters($pages)
|
||||
->leftJoin('SiteTree_Live', '"SiteTree_Live"."ID" = "SiteTree"."ID"')
|
||||
->where('"SiteTree"."Version" > "SiteTree_Live"."Version"');
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($q->execute() as $row) {
|
||||
$ids[] = array('ID'=>$row['ID'],'ParentID'=>$row['ParentID']);
|
||||
}
|
||||
/**
|
||||
* Filters pages which have a status "Removed from Draft".
|
||||
*
|
||||
* @package cms
|
||||
* @subpackage content
|
||||
*/
|
||||
class CMSSiteTreeFilter_StatusRemovedFromDraftPages extends CMSSiteTreeFilter {
|
||||
|
||||
static public function title() {
|
||||
return _t('CMSSiteTreeFilter_StatusRemovedFromDraftPages.Title', 'Live but removed from draft');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out all pages who's status is set to "Removed from draft".
|
||||
*
|
||||
* @see {@link SiteTree::getStatusFlags()}
|
||||
* @return array
|
||||
*/
|
||||
public function pagesIncluded() {
|
||||
$pages = Versioned::get_including_deleted('SiteTree');
|
||||
$pages = $this->applyDefaultFilters($pages);
|
||||
$pages = $pages->filterByCallback(function($page) {
|
||||
// If page is removed from stage but not live
|
||||
return $page->IsDeletedFromStage && $page->ExistsOnLive;
|
||||
});
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
/**
|
||||
* Filters pages which have a status "Draft".
|
||||
*
|
||||
* @package cms
|
||||
* @subpackage content
|
||||
*/
|
||||
class CMSSiteTreeFilter_StatusDraftPages extends CMSSiteTreeFilter {
|
||||
|
||||
static public function title() {
|
||||
return _t('CMSSiteTreeFilter_StatusDraftPages.Title', 'Draft unpublished pages');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out all pages who's status is set to "Draft".
|
||||
*
|
||||
* @see {@link SiteTree::getStatusFlags()}
|
||||
* @return array
|
||||
*/
|
||||
public function pagesIncluded() {
|
||||
$pages = Versioned::get_by_stage('SiteTree', 'Stage');
|
||||
$pages = $this->applyDefaultFilters($pages);
|
||||
$pages = $pages->filterByCallback(function($page) {
|
||||
// If page exists on stage but not on live
|
||||
return (!$page->IsDeletedFromStage && $page->IsAddedToStage);
|
||||
});
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters pages which have a status "Deleted".
|
||||
*
|
||||
* @package cms
|
||||
* @subpackage content
|
||||
*/
|
||||
class CMSSiteTreeFilter_StatusDeletedPages extends CMSSiteTreeFilter {
|
||||
|
||||
protected $childrenMethod = "AllHistoricalChildren";
|
||||
|
||||
static public function title() {
|
||||
return _t('CMSSiteTreeFilter_StatusDeletedPages.Title', 'Deleted pages');
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out all pages who's status is set to "Deleted".
|
||||
*
|
||||
* @see {@link SiteTree::getStatusFlags()}
|
||||
* @return array
|
||||
*/
|
||||
public function pagesIncluded() {
|
||||
$pages = Versioned::get_including_deleted('SiteTree');
|
||||
$pages = $this->applyDefaultFilters($pages);
|
||||
$pages = $pages->filterByCallback(function($page) {
|
||||
// Doesn't exist on either stage or live
|
||||
return $page->IsDeletedFromStage && !$page->ExistsOnLive;
|
||||
});
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,54 +343,10 @@ class CMSSiteTreeFilter_Search extends CMSSiteTreeFilter {
|
||||
* @return Array
|
||||
*/
|
||||
public function pagesIncluded() {
|
||||
$sng = singleton('SiteTree');
|
||||
$ids = array();
|
||||
|
||||
$query = new DataQuery('SiteTree');
|
||||
$query->setQueriedColumns(array('ID', 'ParentID'));
|
||||
|
||||
foreach($this->params as $name => $val) {
|
||||
$SQL_val = Convert::raw2sql($val);
|
||||
|
||||
switch($name) {
|
||||
case 'Term':
|
||||
$query->whereAny(array(
|
||||
"\"URLSegment\" LIKE '%$SQL_val%'",
|
||||
"\"Title\" LIKE '%$SQL_val%'",
|
||||
"\"MenuTitle\" LIKE '%$SQL_val%'",
|
||||
"\"Content\" LIKE '%$SQL_val%'"
|
||||
));
|
||||
break;
|
||||
|
||||
case 'LastEditedFrom':
|
||||
$fromDate = new DateField(null, null, $SQL_val);
|
||||
$query->where("\"LastEdited\" >= '{$fromDate->dataValue()}'");
|
||||
break;
|
||||
|
||||
case 'LastEditedTo':
|
||||
$toDate = new DateField(null, null, $SQL_val);
|
||||
$query->where("\"LastEdited\" <= '{$toDate->dataValue()}'");
|
||||
break;
|
||||
|
||||
case 'ClassName':
|
||||
if($val && $val != 'All') {
|
||||
$query->where("\"ClassName\" = '$SQL_val'");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(!empty($val) && $sng->hasDatabaseField($name)) {
|
||||
$filter = $sng->dbObject($name)->defaultSearchFilter();
|
||||
$filter->setValue($val);
|
||||
$filter->apply($query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($query->execute() as $row) {
|
||||
$ids[] = array('ID' => $row['ID'], 'ParentID' => $row['ParentID']);
|
||||
}
|
||||
|
||||
return $ids;
|
||||
// Filter default records
|
||||
$pages = Versioned::get_by_stage('SiteTree', 'Stage');
|
||||
$pages = $this->applyDefaultFilters($pages);
|
||||
return $this->mapIDs($pages);
|
||||
}
|
||||
}
|
||||
|
@ -1380,7 +1380,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
||||
public function MetaTags($includeTitle = true) {
|
||||
$tags = "";
|
||||
if($includeTitle === true || $includeTitle == 'true') {
|
||||
$tags .= "<title>" . $this->Title . "</title>\n";
|
||||
$tags .= "<title>" . Convert::raw2xml($this->Title) . "</title>\n";
|
||||
}
|
||||
|
||||
$generator = trim(Config::inst()->get('SiteTree', 'meta_generator'));
|
||||
|
@ -38,24 +38,22 @@ class SiteTreeLinkTracking extends DataExtension {
|
||||
$href = Director::makeRelative($link->getAttribute('href'));
|
||||
|
||||
if($href) {
|
||||
if(preg_match('/\[sitetree_link,id=([0-9]+)\]/i', $href, $matches)) {
|
||||
$ID = $matches[1];
|
||||
if(preg_match('/\[(sitetree|file)_link[,\s]id=([0-9]+)\]/i', $href, $matches)) {
|
||||
$type = $matches[1];
|
||||
$id = $matches[2];
|
||||
|
||||
// clear out any broken link classes
|
||||
if($class = $link->getAttribute('class')) {
|
||||
$link->setAttribute('class',
|
||||
preg_replace('/(^ss-broken|ss-broken$| ss-broken )/', null, $class));
|
||||
}
|
||||
|
||||
$linkedPages[] = $ID;
|
||||
if(!DataObject::get_by_id('SiteTree', $ID)) $record->HasBrokenLink = true;
|
||||
|
||||
} else if(substr($href, 0, strlen(ASSETS_DIR) + 1) == ASSETS_DIR.'/') {
|
||||
$candidateFile = File::find(Convert::raw2sql(urldecode($href)));
|
||||
if($candidateFile) {
|
||||
$linkedFiles[] = $candidateFile->ID;
|
||||
} else {
|
||||
$record->HasBrokenFile = true;
|
||||
if($type === 'sitetree') {
|
||||
if(SiteTree::get()->byID($id)) {
|
||||
$linkedPages[] = $id;
|
||||
} else {
|
||||
$record->HasBrokenLink = true;
|
||||
}
|
||||
} else if($type === 'file') {
|
||||
if(File::get()->byID($id)) {
|
||||
$linkedFiles[] = $id;
|
||||
} else {
|
||||
$record->HasBrokenFile = true;
|
||||
}
|
||||
}
|
||||
} else if($href == '' || $href[0] == '/') {
|
||||
$record->HasBrokenLink = true;
|
||||
|
@ -9,6 +9,6 @@ Feature: Create a page
|
||||
And I go to "/admin/pages"
|
||||
And I should see a "Add new" button in CMS Content Toolbar
|
||||
When I press the "Add new" button
|
||||
And I check "Page"
|
||||
And I select the "Page" radio button
|
||||
And I press the "Create" button
|
||||
Then I should see an edit page form
|
||||
|
@ -15,7 +15,7 @@ So that I can link to a external website or a page on my site
|
||||
Scenario: I can link to an internal page
|
||||
Given I select "awesome" in the "Content" HTML field
|
||||
And I press the "Insert Link" button
|
||||
When I check "Page on the site"
|
||||
When I select the "Page on the site" radio button
|
||||
And I fill in the "Page" dropdown with "Home"
|
||||
And I fill in "my desc" for "Link description"
|
||||
And I press the "Insert" button
|
||||
@ -27,7 +27,7 @@ So that I can link to a external website or a page on my site
|
||||
Scenario: I can link to an external URL
|
||||
Given I select "awesome" in the "Content" HTML field
|
||||
And I press the "Insert Link" button
|
||||
When I check "Another website"
|
||||
When I select the "Another website" radio button
|
||||
And I fill in "http://silverstripe.org" for "URL"
|
||||
And I check "Open link in a new window"
|
||||
And I press the "Insert" button
|
||||
@ -38,7 +38,7 @@ So that I can link to a external website or a page on my site
|
||||
Scenario: I can link to a file
|
||||
Given I select "awesome" in the "Content" HTML field
|
||||
When I press the "Insert Link" button
|
||||
When I check "Download a file"
|
||||
When I select the "Download a file" radio button
|
||||
And I fill in the "File" dropdown with "file1.jpg"
|
||||
And I press the "Insert link" button
|
||||
Then the "Content" HTML field should contain "<a href="[file_link,id=1]" target="_blank">awesome</a>"
|
||||
@ -49,7 +49,7 @@ 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<a name=myanchor></a></p>"
|
||||
And I select "awesome" in the "Content" HTML field
|
||||
When I press the "Insert Link" button
|
||||
When I check "Anchor on this page"
|
||||
When I select the "Anchor on this page" radio button
|
||||
# Need to hard-code the id attribute of the <select> here, as there are two form fields to pick from
|
||||
And I select "myanchor" from "Form_EditorToolbarLinkForm_AnchorSelector"
|
||||
And I press the "Insert link" button
|
||||
|
@ -5,8 +5,8 @@ Feature: Manage files
|
||||
So that I can insert them into my content efficiently
|
||||
|
||||
Background:
|
||||
Given a "image" "assets/folder1/file1.jpg"
|
||||
And a "image" "assets/folder1/folder1.1/file2.jpg"
|
||||
Given a "image" "assets/folder1/file1.jpg" was created "2012-01-01 12:00:00"
|
||||
And a "image" "assets/folder1/folder1.1/file2.jpg" was created "2010-01-01 12:00:00"
|
||||
And a "folder" "assets/folder2"
|
||||
And I am logged in with "ADMIN" permissions
|
||||
And I go to "/admin/assets"
|
||||
@ -75,3 +75,11 @@ Feature: Manage files
|
||||
And I press the "Apply Filter" button
|
||||
Then the "Files" table should contain "file1"
|
||||
And the "Files" table should not contain "document"
|
||||
|
||||
Scenario: I can filter out files that don't match the date range
|
||||
Given I expand the "Filter" CMS Panel
|
||||
And I fill in "From" with "2003-01-01"
|
||||
And I fill in "To" with "2011-01-01"
|
||||
And I press the "Apply Filter" button
|
||||
And the "Files" table should contain "file2"
|
||||
And the "Files" table should not contain "file1"
|
||||
|
@ -40,12 +40,59 @@ Feature: Search for a page
|
||||
Then I should not see "Recent Page" in the tree
|
||||
But I should see "Old Page" in the tree
|
||||
|
||||
|
||||
Scenario: I can include deleted pages in my search
|
||||
Given a "page" "Deleted Page"
|
||||
And the "page" "Deleted Page" is unpublished
|
||||
And the "page" "Deleted Page" is deleted
|
||||
When I press the "Apply Filter" button
|
||||
Then I should not see "Deleted Page" in the tree
|
||||
When I select "All pages, including deleted" from "Pages"
|
||||
And I press the "Apply Filter" button
|
||||
Then I should see "Deleted Page" in the tree
|
||||
Then I should see "Deleted Page" in the tree
|
||||
|
||||
Scenario: I can include only deleted pages in my search
|
||||
Given a "page" "Deleted Page"
|
||||
And the "page" "Deleted Page" is unpublished
|
||||
And the "page" "Deleted Page" is deleted
|
||||
When I press the "Apply Filter" button
|
||||
Then I should not see "Deleted Page" in the tree
|
||||
When I select "Deleted pages" from "Pages"
|
||||
And I press the "Apply Filter" button
|
||||
Then I should see "Deleted Page" in the tree
|
||||
And I should not see "About Us" in the tree
|
||||
|
||||
Scenario: I can include draft pages in my search
|
||||
Given a "page" "Draft Page"
|
||||
And the "page" "Draft Page" is not published
|
||||
When I press the "Apply Filter" button
|
||||
Then I should see "Draft Page" in the tree
|
||||
When I select "Draft unpublished pages" from "Pages"
|
||||
And I press the "Apply Filter" button
|
||||
Then I should see "Draft Page" in the tree
|
||||
And I should not see "About Us" in the tree
|
||||
|
||||
Scenario: I can include changed pages in my search
|
||||
When I click on "About Us" in the tree
|
||||
Then I should see an edit page form
|
||||
|
||||
When I fill in the "Content" HTML field with "my new content"
|
||||
And I press the "Save draft" button
|
||||
Then I should see "Saved" in the "button#Form_EditForm_action_save" element
|
||||
|
||||
When I go to "/admin/pages"
|
||||
And I expand the "Filter" CMS Panel
|
||||
When I select "Changed pages" from "Pages"
|
||||
And I press the "Apply Filter" button
|
||||
Then I should see "About Us" in the tree
|
||||
And I should not see "Home" in the tree
|
||||
|
||||
Scenario: I can include live pages in my search
|
||||
Given a "page" "Live Page"
|
||||
And the "page" "Live Page" is published
|
||||
And the "page" "Live Page" is deleted
|
||||
When I press the "Apply Filter" button
|
||||
Then I should not see "Live Page" in the tree
|
||||
When I select "Live but removed from draft" from "Pages"
|
||||
And I press the "Apply Filter" button
|
||||
Then I should see "Live Page" in the tree
|
||||
And I should not see "About Us" in the tree
|
||||
|
@ -56,7 +56,8 @@ class CMSSiteTreeFilterTest extends SapphireTest {
|
||||
$changedPage->Title = 'Changed';
|
||||
$changedPage->write();
|
||||
|
||||
$f = new CMSSiteTreeFilter_ChangedPages();
|
||||
// Check that only changed pages are returned
|
||||
$f = new CMSSiteTreeFilter_ChangedPages(array('Term' => 'Changed'));
|
||||
$results = $f->pagesIncluded();
|
||||
|
||||
$this->assertTrue($f->isPageIncluded($changedPage));
|
||||
@ -66,6 +67,11 @@ class CMSSiteTreeFilterTest extends SapphireTest {
|
||||
array('ID' => $changedPage->ID, 'ParentID' => 0),
|
||||
$results[0]
|
||||
);
|
||||
|
||||
// Check that only changed pages are returned
|
||||
$f = new CMSSiteTreeFilter_ChangedPages(array('Term' => 'No Matches'));
|
||||
$results = $f->pagesIncluded();
|
||||
$this->assertEquals(0, count($results));
|
||||
}
|
||||
|
||||
public function testDeletedPagesFilter() {
|
||||
@ -79,9 +85,77 @@ class CMSSiteTreeFilterTest extends SapphireTest {
|
||||
sprintf('"SiteTree_Live"."ID" = %d', $deletedPageID)
|
||||
);
|
||||
|
||||
$f = new CMSSiteTreeFilter_DeletedPages();
|
||||
$results = $f->pagesIncluded();
|
||||
|
||||
$f = new CMSSiteTreeFilter_DeletedPages(array('Term' => 'Page'));
|
||||
$this->assertTrue($f->isPageIncluded($deletedPage));
|
||||
|
||||
// Check that only changed pages are returned
|
||||
$f = new CMSSiteTreeFilter_DeletedPages(array('Term' => 'No Matches'));
|
||||
$this->assertFalse($f->isPageIncluded($deletedPage));
|
||||
}
|
||||
|
||||
public function testStatusDraftPagesFilter() {
|
||||
$draftPage = $this->objFromFixture('Page', 'page4');
|
||||
$draftPage->publish('Stage', 'Stage');
|
||||
$draftPage = Versioned::get_one_by_stage(
|
||||
'SiteTree',
|
||||
'Stage',
|
||||
sprintf('"SiteTree"."ID" = %d', $draftPage->ID)
|
||||
);
|
||||
|
||||
// Check draft page is shown
|
||||
$f = new CMSSiteTreeFilter_StatusDraftPages(array('Term' => 'Page'));
|
||||
$this->assertTrue($f->isPageIncluded($draftPage));
|
||||
|
||||
// Check filter respects parameters
|
||||
$f = new CMSSiteTreeFilter_StatusDraftPages(array('Term' => 'No Match'));
|
||||
$this->assertEmpty($f->isPageIncluded($draftPage));
|
||||
|
||||
// Ensures empty array returned if no data to show
|
||||
$f = new CMSSiteTreeFilter_StatusDraftPages();
|
||||
$draftPage->delete();
|
||||
$this->assertEmpty($f->isPageIncluded($draftPage));
|
||||
}
|
||||
|
||||
public function testStatusRemovedFromDraftFilter() {
|
||||
$removedDraftPage = $this->objFromFixture('Page', 'page6');
|
||||
$removedDraftPage->doPublish();
|
||||
$removedDraftPage->deleteFromStage('Stage');
|
||||
$removedDraftPage = Versioned::get_one_by_stage(
|
||||
'SiteTree',
|
||||
'Live',
|
||||
sprintf('"SiteTree"."ID" = %d', $removedDraftPage->ID)
|
||||
);
|
||||
|
||||
// Check live-only page is included
|
||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(array('LastEditedFrom' => '2000-01-01 00:00'));
|
||||
$this->assertTrue($f->isPageIncluded($removedDraftPage));
|
||||
|
||||
// Check filter is respected
|
||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(array('LastEditedTo' => '1999-01-01 00:00'));
|
||||
$this->assertEmpty($f->isPageIncluded($removedDraftPage));
|
||||
|
||||
// Ensures empty array returned if no data to show
|
||||
$f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages();
|
||||
$removedDraftPage->delete();
|
||||
$this->assertEmpty($f->isPageIncluded($removedDraftPage));
|
||||
}
|
||||
|
||||
public function testStatusDeletedFilter() {
|
||||
$deletedPage = $this->objFromFixture('Page', 'page7');
|
||||
$deletedPage->publish('Stage', 'Live');
|
||||
$deletedPageID = $deletedPage->ID;
|
||||
|
||||
// Can't use straight $blah->delete() as that blows it away completely and test fails
|
||||
$deletedPage->deleteFromStage('Live');
|
||||
$deletedPage->deleteFromStage('Draft');
|
||||
$checkParentExists = Versioned::get_latest_version('SiteTree', $deletedPageID);
|
||||
|
||||
// Check deleted page is included
|
||||
$f = new CMSSiteTreeFilter_StatusDeletedPages(array('Title' => 'Page'));
|
||||
$this->assertTrue($f->isPageIncluded($checkParentExists));
|
||||
|
||||
// Check filter is respected
|
||||
$f = new CMSSiteTreeFilter_StatusDeletedPages(array('Title' => 'Bobby'));
|
||||
$this->assertFalse($f->isPageIncluded($checkParentExists));
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,18 @@ Page:
|
||||
Title: Page 2
|
||||
page3:
|
||||
Title: Page 3
|
||||
page4:
|
||||
Title: Page 4
|
||||
page5:
|
||||
Title: Page 5
|
||||
Content: 'Default text'
|
||||
page6:
|
||||
Title: Page 6
|
||||
page7:
|
||||
Title: Page 7
|
||||
page7a:
|
||||
Parent: =>Page.page7
|
||||
Title: Page 7a
|
||||
page2a:
|
||||
Parent: =>Page.page2
|
||||
Title: Page 2a
|
||||
|
@ -46,18 +46,6 @@ class SiteTreeBrokenLinksTest extends SapphireTest {
|
||||
$this->assertTrue($rp->HasBrokenLink, 'Broken redirector page IS marked as such');
|
||||
}
|
||||
|
||||
public function testBrokenAssetLinks() {
|
||||
$obj = $this->objFromFixture('Page','content');
|
||||
|
||||
$obj->Content = '<a href="assets/nofilehere.pdf">this is a broken link to a pdf file</a>';
|
||||
$obj->syncLinkTracking();
|
||||
$this->assertTrue($obj->HasBrokenFile, 'Page has a broken file');
|
||||
|
||||
$obj->Content = '<a href="assets/privacypolicy.pdf">this is not a broken file link</a>';
|
||||
$obj->syncLinkTracking();
|
||||
$this->assertFalse($obj->HasBrokenFile, 'Page does NOT have a broken file');
|
||||
}
|
||||
|
||||
public function testDeletingFileMarksBackedPagesAsBroken() {
|
||||
// Test entry
|
||||
$file = new File();
|
||||
@ -65,7 +53,10 @@ class SiteTreeBrokenLinksTest extends SapphireTest {
|
||||
$file->write();
|
||||
|
||||
$obj = $this->objFromFixture('Page','content');
|
||||
$obj->Content = '<a href="assets/test-file.pdf">link to a pdf file</a>';
|
||||
$obj->Content = sprintf(
|
||||
'<p><a href="[file_link,id=%d]">Working Link</a></p>',
|
||||
$file->ID
|
||||
);
|
||||
$obj->write();
|
||||
$this->assertTrue($obj->doPublish());
|
||||
// Confirm that it isn't marked as broken to begin with
|
||||
|
@ -31,6 +31,16 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
$this->assertEquals(array(), $sitetree->LinkTracking()->getIdList(), 'Link tracking is removed when links are.');
|
||||
|
||||
// Legacy support - old CMS versions added link shortcodes with spaces instead of commas
|
||||
$editor->setValue("<a href=\"[sitetree_link id=$aboutID]\">Example Link</a>");
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
$this->assertEquals(
|
||||
array($aboutID => $aboutID),
|
||||
$sitetree->LinkTracking()->getIdList(),
|
||||
'Link tracking with space instead of comma in shortcode works.'
|
||||
);
|
||||
}
|
||||
|
||||
public function testFileLinkTracking() {
|
||||
@ -38,7 +48,10 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
$editor = new HtmlEditorField('Content');
|
||||
$fileID = $this->idFromFixture('File', 'example_file');
|
||||
|
||||
$editor->setValue('<a href="assets/example.pdf">Example File</a>');
|
||||
$editor->setValue(sprintf(
|
||||
'<p><a href="[file_link,id=%d]">Example File</a></p>',
|
||||
$fileID
|
||||
));
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
$this->assertEquals (
|
||||
@ -49,6 +62,19 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
$this->assertEquals(array(), $sitetree->ImageTracking()->getIdList(), 'Asset tracking is removed with links.');
|
||||
|
||||
// Legacy support - old CMS versions added link shortcodes with spaces instead of commas
|
||||
$editor->setValue(sprintf(
|
||||
'<p><a href="[file_link id=%d]">Example File</a></p>',
|
||||
$fileID
|
||||
));
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
$this->assertEquals(
|
||||
array($fileID => $fileID),
|
||||
$sitetree->ImageTracking()->getIDList(),
|
||||
'Link tracking with space instead of comma in shortcode works.'
|
||||
);
|
||||
}
|
||||
|
||||
public function testImageInsertion() {
|
||||
@ -94,7 +120,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
);
|
||||
}
|
||||
|
||||
public function testBrokenLinkTracking() {
|
||||
public function testBrokenSiteTreeLinkTracking() {
|
||||
$sitetree = new SiteTree();
|
||||
$editor = new HtmlEditorField('Content');
|
||||
|
||||
@ -117,14 +143,38 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
$this->assertFalse((bool) $sitetree->HasBrokenLink);
|
||||
}
|
||||
|
||||
public function testBrokenFileLinkTracking() {
|
||||
$sitetree = new SiteTree();
|
||||
$editor = new HtmlEditorField('Content');
|
||||
|
||||
$this->assertFalse((bool) $sitetree->HasBrokenFile);
|
||||
|
||||
$editor->setValue('<p><a href="[file_link,id=0]">Broken Link</a></p>');
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
|
||||
$this->assertTrue($sitetree->HasBrokenFile);
|
||||
|
||||
$editor->setValue(sprintf (
|
||||
'<p><a href="[file_link,id=%d]">Working Link</a></p>',
|
||||
$this->idFromFixture('File', 'example_file')
|
||||
));
|
||||
$sitetree->HasBrokenFile = false;
|
||||
$editor->saveInto($sitetree);
|
||||
$sitetree->write();
|
||||
|
||||
$this->assertFalse((bool) $sitetree->HasBrokenFile);
|
||||
}
|
||||
|
||||
public function testBrokenLinkHighlighting() {
|
||||
$sitetree = new SiteTree();
|
||||
$editor = new HtmlEditorField('Content');
|
||||
|
||||
// SiteTree link highlighting
|
||||
$editor->setValue('<a href="[sitetree_link,id=0]">Broken Link</a>');
|
||||
|
||||
$element = new SimpleXMLElement(html_entity_decode((string) new SimpleXMLElement($editor->Field())));
|
||||
$this->assertContains('ss-broken', (string) $element['class'], 'A broken link class is added to broken links');
|
||||
$this->assertContains('ss-broken', (string) $element['class'], 'A broken SiteTree link is highlighted');
|
||||
|
||||
$editor->setValue(sprintf (
|
||||
'<a href="[sitetree_link,id=%d]">Working Link</a>',
|
||||
@ -133,6 +183,20 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
||||
|
||||
$element = new SimpleXMLElement(html_entity_decode((string) new SimpleXMLElement($editor->Field())));
|
||||
$this->assertNotContains('ss-broken', (string) $element['class']);
|
||||
|
||||
// File link highlighting
|
||||
$editor->setValue('<a href="[file_link,id=0]">Broken Link</a>');
|
||||
|
||||
$element = new SimpleXMLElement(html_entity_decode((string) new SimpleXMLElement($editor->Field())));
|
||||
$this->assertContains('ss-broken', (string) $element['class'], 'A broken File link is highlighted');
|
||||
|
||||
$editor->setValue(sprintf (
|
||||
'<a href="[file_link,id=%d]">Working Link</a>',
|
||||
$this->idFromFixture('File', 'example_file')
|
||||
));
|
||||
|
||||
$element = new SimpleXMLElement(html_entity_decode((string) new SimpleXMLElement($editor->Field())));
|
||||
$this->assertNotContains('ss-broken', (string) $element['class']);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -944,6 +944,29 @@ class SiteTreeTest extends SapphireTest {
|
||||
Config::inst()->update('SiteTree', 'meta_generator', $generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests SiteTree::MetaTags
|
||||
* Note that this test makes no assumption on the closing of tags (other than <title></title>)
|
||||
*/
|
||||
public function testMetaTags() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
$page = $this->objFromFixture('Page', 'metapage');
|
||||
|
||||
// Test with title
|
||||
$meta = $page->MetaTags();
|
||||
$charset = Config::inst()->get('ContentNegotiator', 'encoding');
|
||||
$this->assertContains('<meta http-equiv="Content-type" content="text/html; charset='.$charset.'"', $meta);
|
||||
$this->assertContains('<meta name="description" content="The <br /> and <br> tags"', $meta);
|
||||
$this->assertContains('<link rel="canonical" href="http://www.mysite.com/html-and-xml"', $meta);
|
||||
$this->assertContains('<meta name="x-page-id" content="'.$page->ID.'"', $meta);
|
||||
$this->assertContains('<meta name="x-cms-edit-link" content="'.$page->CMSEditLink().'" />', $meta);
|
||||
$this->assertContains('<title>HTML & XML</title>', $meta);
|
||||
|
||||
// Test without title
|
||||
$meta = $page->MetaTags(false);
|
||||
$this->assertNotContains('<title>', $meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that orphaned pages are handled correctly
|
||||
*/
|
||||
|
@ -1,104 +1,107 @@
|
||||
Group:
|
||||
editors:
|
||||
Title: Editors
|
||||
admins:
|
||||
Title: Administrators
|
||||
allsections:
|
||||
Title: All Section Editors
|
||||
securityadmins:
|
||||
Title: Security Admins
|
||||
editors:
|
||||
Title: Editors
|
||||
admins:
|
||||
Title: Administrators
|
||||
allsections:
|
||||
Title: All Section Editors
|
||||
securityadmins:
|
||||
Title: Security Admins
|
||||
|
||||
Permission:
|
||||
admins:
|
||||
Code: ADMIN
|
||||
Group: =>Group.admins
|
||||
editors:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
Group: =>Group.editors
|
||||
allsections:
|
||||
Code: CMS_ACCESS_LeftAndMain
|
||||
Group: =>Group.allsections
|
||||
securityadmins:
|
||||
Code: CMS_ACCESS_SecurityAdmin
|
||||
Group: =>Group.securityadmins
|
||||
admins:
|
||||
Code: ADMIN
|
||||
Group: =>Group.admins
|
||||
editors:
|
||||
Code: CMS_ACCESS_CMSMain
|
||||
Group: =>Group.editors
|
||||
allsections:
|
||||
Code: CMS_ACCESS_LeftAndMain
|
||||
Group: =>Group.allsections
|
||||
securityadmins:
|
||||
Code: CMS_ACCESS_SecurityAdmin
|
||||
Group: =>Group.securityadmins
|
||||
|
||||
Member:
|
||||
editor:
|
||||
FirstName: Test
|
||||
Surname: Editor
|
||||
Groups: =>Group.editors
|
||||
admin:
|
||||
FirstName: Test
|
||||
Surname: Administrator
|
||||
Groups: =>Group.admins
|
||||
allsections:
|
||||
Groups: =>Group.allsections
|
||||
securityadmin:
|
||||
Groups: =>Group.securityadmins
|
||||
editor:
|
||||
FirstName: Test
|
||||
Surname: Editor
|
||||
Groups: =>Group.editors
|
||||
admin:
|
||||
FirstName: Test
|
||||
Surname: Administrator
|
||||
Groups: =>Group.admins
|
||||
allsections:
|
||||
Groups: =>Group.allsections
|
||||
securityadmin:
|
||||
Groups: =>Group.securityadmins
|
||||
|
||||
Page:
|
||||
home:
|
||||
Title: Home
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
about:
|
||||
Title: About Us
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
staff:
|
||||
Title: Staff
|
||||
URLSegment: my-staff
|
||||
Parent: =>Page.about
|
||||
ceo:
|
||||
Title: CEO
|
||||
Parent: =>Page.staff
|
||||
staffduplicate:
|
||||
Title: Staff
|
||||
URLSegment: my-staff
|
||||
Parent: =>Page.about
|
||||
products:
|
||||
Title: Products
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.editors
|
||||
product1:
|
||||
Title: 1.1 Test Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product2:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product3:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product4:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
contact:
|
||||
Title: Contact Us
|
||||
object:
|
||||
Title: Object
|
||||
controller:
|
||||
Title: Controller
|
||||
numericonly:
|
||||
Title: 1930
|
||||
home:
|
||||
Title: Home
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
about:
|
||||
Title: About Us
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
staff:
|
||||
Title: Staff
|
||||
URLSegment: my-staff
|
||||
Parent: =>Page.about
|
||||
ceo:
|
||||
Title: CEO
|
||||
Parent: =>Page.staff
|
||||
staffduplicate:
|
||||
Title: Staff
|
||||
URLSegment: my-staff
|
||||
Parent: =>Page.about
|
||||
products:
|
||||
Title: Products
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.editors
|
||||
product1:
|
||||
Title: 1.1 Test Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product2:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product3:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: Inherit
|
||||
product4:
|
||||
Title: Another Product
|
||||
Parent: =>Page.products
|
||||
CanEditType: OnlyTheseUsers
|
||||
EditorGroups: =>Group.admins
|
||||
contact:
|
||||
Title: Contact Us
|
||||
object:
|
||||
Title: Object
|
||||
controller:
|
||||
Title: Controller
|
||||
numericonly:
|
||||
Title: 1930
|
||||
metapage:
|
||||
Title: 'HTML & XML'
|
||||
MetaDescription: 'The <br /> and <br> tags'
|
||||
ExtraMeta: '<link rel="canonical" href="http://www.mysite.com/html-and-xml" />'
|
||||
|
||||
SiteTreeTest_Conflicted:
|
||||
parent:
|
||||
Title: Parent
|
||||
parent:
|
||||
Title: Parent
|
||||
|
||||
ErrorPage:
|
||||
404:
|
||||
Title: Page not Found
|
||||
ErrorCode: 404
|
||||
404:
|
||||
Title: Page not Found
|
||||
ErrorCode: 404
|
||||
|
||||
RedirectorPage:
|
||||
external:
|
||||
Title: External
|
||||
URLSegment: external
|
||||
RedirectionType: External
|
||||
ExternalURL: "http://www.google.com?a&b"
|
||||
|
||||
external:
|
||||
Title: External
|
||||
URLSegment: external
|
||||
RedirectionType: External
|
||||
ExternalURL: "http://www.google.com?a&b"
|
||||
|
Loading…
x
Reference in New Issue
Block a user