API Refactor usages of HTMLText -> HTMLFragment

API Revert hack in VirtualPage
API Respect default_cast
This commit is contained in:
Daniel Hensby 2015-02-10 23:13:55 +00:00 committed by Damian Mooyman
parent 3a395e6d56
commit dc8d4ffe0b
6 changed files with 100 additions and 68 deletions

View File

@ -74,6 +74,18 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
'childfilter', 'childfilter',
); );
private static $casting = array(
'TreeIsFiltered' => 'Boolean',
'AddForm' => 'HTMLFragment',
'LinkPages' => 'Text',
'Link' => 'Text',
'ListViewForm' => 'HTMLFragment',
'ExtraTreeTools' => 'HTMLFragment',
'SiteTreeHints' => 'HTMLFragment',
'SecurityID' => 'Text',
'SiteTreeAsUL' => 'HTMLFragment',
);
public function init() { public function init() {
// set reading lang // set reading lang
if(SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) { if(SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) {
@ -799,7 +811,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$columns->setFieldCasting(array( $columns->setFieldCasting(array(
'Created' => 'DBDatetime->Ago', 'Created' => 'DBDatetime->Ago',
'LastEdited' => 'DBDatetime->FormatFromSettings', 'LastEdited' => 'DBDatetime->FormatFromSettings',
'getTreeTitle' => 'HTMLText' 'getTreeTitle' => 'HTMLFragment'
)); ));
$controller = $this; $controller = $this;

View File

@ -127,7 +127,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
"MenuTitle" => "Varchar(100)", "MenuTitle" => "Varchar(100)",
"Content" => "HTMLText", "Content" => "HTMLText",
"MetaDescription" => "Text", "MetaDescription" => "Text",
"ExtraMeta" => "HTMLText('meta, link')", "ExtraMeta" => "HTMLFragment(['whitelist' => ['meta', 'link']])",
"ShowInMenus" => "Boolean", "ShowInMenus" => "Boolean",
"ShowInSearch" => "Boolean", "ShowInSearch" => "Boolean",
"Sort" => "Int", "Sort" => "Int",
@ -156,11 +156,15 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
); );
private static $casting = array( private static $casting = array(
"Breadcrumbs" => "HTMLText", "Breadcrumbs" => "HTMLFragment",
"LastEdited" => "Datetime",
"Created" => "Datetime",
'Link' => 'Text', 'Link' => 'Text',
'RelativeLink' => 'Text', 'RelativeLink' => 'Text',
'AbsoluteLink' => 'Text', 'AbsoluteLink' => 'Text',
'TreeTitle' => 'HTMLText', 'CMSEditLink' => 'Text',
'TreeTitle' => 'HTMLFragment',
'MetaTags' => 'HTMLFragment',
); );
private static $defaults = array( private static $defaults = array(
@ -685,7 +689,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @param boolean $unlinked Whether to link page titles. * @param boolean $unlinked Whether to link page titles.
* @param boolean|string $stopAtPageType ClassName of a page to stop the upwards traversal. * @param boolean|string $stopAtPageType ClassName of a page to stop the upwards traversal.
* @param boolean $showHidden Include pages marked with the attribute ShowInMenus = 0 * @param boolean $showHidden Include pages marked with the attribute ShowInMenus = 0
* @return HTMLText The breadcrumb trail. * @return string The breadcrumb trail.
*/ */
public function Breadcrumbs($maxDepth = 20, $unlinked = false, $stopAtPageType = false, $showHidden = false) { public function Breadcrumbs($maxDepth = 20, $unlinked = false, $stopAtPageType = false, $showHidden = false) {
$pages = $this->getBreadcrumbItems($maxDepth, $stopAtPageType, $showHidden); $pages = $this->getBreadcrumbItems($maxDepth, $stopAtPageType, $showHidden);
@ -762,6 +766,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
*/ */
public function NestedTitle($level = 2, $separator = " - ") { public function NestedTitle($level = 2, $separator = " - ") {
$item = $this; $item = $this;
$parts = [];
while($item && $level > 0) { while($item && $level > 0) {
$parts[] = $item->Title; $parts[] = $item->Title;
$item = $item->Parent; $item = $item->Parent;
@ -1058,10 +1063,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return SiteConfig * @return SiteConfig
*/ */
public function getSiteConfig() { public function getSiteConfig() {
$configs = $this->invokeWithExtensions('alternateSiteConfig');
if($this->hasMethod('alternateSiteConfig')) { foreach(array_filter($configs) as $config) {
$altConfig = $this->alternateSiteConfig(); return $config;
if($altConfig) return $altConfig;
} }
return SiteConfig::current_site_config(); return SiteConfig::current_site_config();
@ -1190,6 +1194,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
// then see which ones the user has permission on // then see which ones the user has permission on
$groupedByParent = array(); $groupedByParent = array();
foreach($potentiallyInherited as $item) { foreach($potentiallyInherited as $item) {
/** @var SiteTree $item */
if($item->ParentID) { if($item->ParentID) {
if(!isset($groupedByParent[$item->ParentID])) $groupedByParent[$item->ParentID] = array(); if(!isset($groupedByParent[$item->ParentID])) $groupedByParent[$item->ParentID] = array();
$groupedByParent[$item->ParentID][] = $item->ID; $groupedByParent[$item->ParentID][] = $item->ID;
@ -1222,7 +1227,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
// Cache the results // Cache the results
if(empty(self::$cache_permissions[$cacheKey])) self::$cache_permissions[$cacheKey] = array(); if(empty(self::$cache_permissions[$cacheKey])) self::$cache_permissions[$cacheKey] = array();
self::$cache_permissions[$cacheKey] = $combinedStageResult + self::$cache_permissions[$cacheKey]; self::$cache_permissions[$cacheKey] = $combinedStageResult + self::$cache_permissions[$cacheKey];
return $combinedStageResult; return $combinedStageResult;
} else { } else {
return array(); return array();
@ -1302,8 +1306,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
} else { } else {
$deletable = $editableIDs; $deletable = $editableIDs;
} }
} else {
$deletable = array();
} }
// Convert the array of deletable IDs into a map of the original IDs with true/false as the value // Convert the array of deletable IDs into a map of the original IDs with true/false as the value
@ -1323,7 +1325,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
public function collateDescendants($condition, &$collator) { public function collateDescendants($condition, &$collator) {
if($children = $this->Children()) { if($children = $this->Children()) {
foreach($children as $item) { foreach($children as $item) {
if(eval("return $condition;")) $collator[] = $item;
if(eval("return $condition;")) {
$collator[] = $item;
}
/** @var SiteTree $item */
$item->collateDescendants($condition, $collator); $item->collateDescendants($condition, $collator);
} }
return true; return true;
@ -1339,23 +1345,29 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* @return string The XHTML metatags * @return string The XHTML metatags
*/ */
public function MetaTags($includeTitle = true) { public function MetaTags($includeTitle = true) {
$tags = ""; $tags = array();
if($includeTitle === true || $includeTitle == 'true') { if($includeTitle && strtolower($includeTitle) != 'false') {
$tags .= "<title>" . Convert::raw2xml($this->Title) . "</title>\n"; $tags[] = FormField::create_tag('title', array(), $this->obj('Title')->forTemplate());
} }
$generator = trim(Config::inst()->get('SiteTree', 'meta_generator')); $generator = trim(Config::inst()->get('SiteTree', 'meta_generator'));
if (!empty($generator)) { if (!empty($generator)) {
$tags .= "<meta name=\"generator\" content=\"" . Convert::raw2att($generator) . "\" />\n"; $tags[] = FormField::create_tag('meta', array(
'name' => 'generator',
'content' => $generator,
));
} }
$charset = Config::inst()->get('ContentNegotiator', 'encoding'); $charset = Config::inst()->get('ContentNegotiator', 'encoding');
$tags .= "<meta http-equiv=\"Content-type\" content=\"text/html; charset=$charset\" />\n"; $tags[] = FormField::create_tag('meta', array(
'http-equiv' => 'Content-Type',
'content' => 'text/html; charset=' . $charset,
));
if($this->MetaDescription) { if($this->MetaDescription) {
$tags .= "<meta name=\"description\" content=\"" . Convert::raw2att($this->MetaDescription) . "\" />\n"; $tags[] = FormField::create_tag('meta', array(
} 'name' => 'description',
if($this->ExtraMeta) { 'content' => $this->MetaDescription,
$tags .= $this->ExtraMeta . "\n"; ));
} }
if(Permission::check('CMS_ACCESS_CMSMain') if(Permission::check('CMS_ACCESS_CMSMain')
@ -1363,8 +1375,19 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
&& !$this instanceof ErrorPage && !$this instanceof ErrorPage
&& $this->ID > 0 && $this->ID > 0
) { ) {
$tags .= "<meta name=\"x-page-id\" content=\"{$this->ID}\" />\n"; $tags[] = FormField::create_tag('meta', array(
$tags .= "<meta name=\"x-cms-edit-link\" content=\"" . $this->CMSEditLink() . "\" />\n"; 'name' => 'x-page-id',
'content' => $this->obj('ID')->forTemplate(),
));
$tags[] = FormField::create_tag('meta', array(
'name' => 'x-cms-edit-link',
'content' => $this->obj('CMSEditLink')->forTemplate(),
));
}
$tags = implode("\n", $tags);
if($this->ExtraMeta) {
$tags .= $this->obj('ExtraMeta')->forTemplate();
} }
$this->extend('MetaTags', $tags); $this->extend('MetaTags', $tags);

View File

@ -494,24 +494,21 @@ class VirtualPage_Controller extends Page_Controller {
* @throws Exception Any error other than a 'no method' error. * @throws Exception Any error other than a 'no method' error.
*/ */
public function __call($method, $args) { public function __call($method, $args) {
try { // Check if we can safely call this method before passing it back
// to custom methods.
if($this->getExtraMethodConfig($method)) {
return parent::__call($method, $args); return parent::__call($method, $args);
} catch (Exception $e) {
// Hack... detect exception type. We really should use exception subclasses.
// if the exception isn't a 'no method' error, rethrow it
if ($e->getCode() !== 2175) {
throw $e;
}
$original = $this->copyContentFrom();
$controller = ModelAsController::controller_for($original);
// Ensure request/response data is available on virtual controller
$controller->setRequest($this->getRequest());
$controller->response = $this->response; // @todo - replace with getter/setter in 3.3
return call_user_func_array(array($controller, $method), $args);
} }
// Pass back to copied page
$original = $this->copyContentFrom();
$controller = ModelAsController::controller_for($original);
// Ensure request/response data is available on virtual controller
$controller->setRequest($this->getRequest());
$controller->response = $this->response; // @todo - replace with getter/setter in 3.3
return call_user_func_array(array($controller, $method), $args);
} }
} }

View File

@ -8,17 +8,17 @@
<% if $TreeIsFiltered %> <% if $TreeIsFiltered %>
<div class="cms-notice cms-tree-filtered"> <div class="cms-notice cms-tree-filtered">
<strong><% _t('CMSMain.ListFiltered', 'Showing search results.') %></strong> <strong><% _t('CMSMain.ListFiltered', 'Showing search results.') %></strong>
<a href="$LinkPages" class="cms-panel-link"> <a href="$LinkPages.ATT" class="cms-panel-link">
<% _t('CMSMain.TreeFilteredClear', 'Clear') %> <% _t('CMSMain.TreeFilteredClear', 'Clear') %>
</a> </a>
<div class="cms-list" data-url-list="$Link(getListViewHTML)"> <div class="cms-list" data-url-list="$Link(getListViewHTML)">
$ListViewForm $ListViewForm
</div> </div>
</div> </div>
<% else %> <% else %>
<div class="cms-list" data-url-list="$Link(getListViewHTML)"> <div class="cms-list" data-url-list="$Link('getListViewHTML').ATT">
$ListViewForm $ListViewForm
</div> </div>
<% end_if %> <% end_if %>

View File

@ -15,35 +15,35 @@ $ExtraTreeTools
</a> </a>
<div class="cms-tree <% if $TreeIsFiltered %>filtered-list<% end_if %>" <div class="cms-tree <% if $TreeIsFiltered %>filtered-list<% end_if %>"
data-url-tree="$LinkWithSearch($Link(getsubtree))" data-url-tree="$LinkWithSearch($Link(getsubtree)).ATT"
data-url-savetreenode="$Link(savetreenode)" data-url-savetreenode="$Link(savetreenode).ATT"
data-url-updatetreenodes="$Link(updatetreenodes)" data-url-updatetreenodes="$Link(updatetreenodes).ATT"
data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&amp;PageType=%s')}" data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&amp;PageType=%s').ATT}"
data-url-editpage="$LinkPageEdit('%s')" data-url-editpage="$LinkPageEdit('%s').ATT"
data-url-duplicate="{$Link('duplicate/%s')}" data-url-duplicate="{$Link('duplicate/%s').ATT}"
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s')}" data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
data-url-listview="{$Link('?view=list')}" data-url-listview="{$Link('?view=list').ATT}"
data-hints="$SiteTreeHints.XML" data-hints="$SiteTreeHints.ATT"
data-childfilter="$Link('childfilter')" data-childfilter="$Link('childfilter').ATT"
data-extra-params="SecurityID=$SecurityID"> data-extra-params="SecurityID=$SecurityID.ATT">
$SiteTreeAsUL $SiteTreeAsUL
</div> </div>
</div> </div>
<% else %> <% else %>
<div class="cms-tree <% if $TreeIsFiltered %>filtered-list<% end_if %>" <div class="cms-tree <% if $TreeIsFiltered %>filtered-list<% end_if %>"
data-url-tree="$LinkWithSearch($Link(getsubtree))" data-url-tree="$LinkWithSearch($Link(getsubtree)).ATT"
data-url-savetreenode="$Link(savetreenode)" data-url-savetreenode="$Link(savetreenode).ATT"
data-url-updatetreenodes="$Link(updatetreenodes)" data-url-updatetreenodes="$Link(updatetreenodes).ATT"
data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&amp;PageType=%s')}" data-url-addpage="{$LinkPageAdd('AddForm/?action_doAdd=1', 'ParentID=%s&amp;PageType=%s').ATT}"
data-url-editpage="$LinkPageEdit('%s')" data-url-editpage="$LinkPageEdit('%s').ATT"
data-url-duplicate="{$Link('duplicate/%s')}" data-url-duplicate="{$Link('duplicate/%s').ATT}"
data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s')}" data-url-duplicatewithchildren="{$Link('duplicatewithchildren/%s').ATT}"
data-url-listview="{$Link('?view=list')}" data-url-listview="{$Link('?view=list').ATT}"
data-hints="$SiteTreeHints.XML" data-hints="$SiteTreeHints.ATT"
data-childfilter="$Link('childfilter')" data-childfilter="$Link('childfilter').ATT"
data-extra-params="SecurityID=$SecurityID"> data-extra-params="SecurityID=$SecurityID.ATT">
$SiteTreeAsUL $SiteTreeAsUL
</div> </div>

View File

@ -1093,11 +1093,11 @@ class SiteTreeTest extends SapphireTest {
// Test with title // Test with title
$meta = $page->MetaTags(); $meta = $page->MetaTags();
$charset = Config::inst()->get('ContentNegotiator', 'encoding'); $charset = Config::inst()->get('ContentNegotiator', 'encoding');
$this->assertContains('<meta http-equiv="Content-type" content="text/html; charset='.$charset.'"', $meta); $this->assertContains('<meta http-equiv="Content-Type" content="text/html; charset='.$charset.'"', $meta);
$this->assertContains('<meta name="description" content="The &lt;br /&gt; and &lt;br&gt; tags"', $meta); $this->assertContains('<meta name="description" content="The &lt;br /&gt; and &lt;br&gt; tags"', $meta);
$this->assertContains('<link rel="canonical" href="http://www.mysite.com/html-and-xml"', $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-page-id" content="'.$page->ID.'"', $meta);
$this->assertContains('<meta name="x-cms-edit-link" content="'.$page->CMSEditLink().'" />', $meta); $this->assertContains('<meta name="x-cms-edit-link" content="'.$page->CMSEditLink().'"', $meta);
$this->assertContains('<title>HTML &amp; XML</title>', $meta); $this->assertContains('<title>HTML &amp; XML</title>', $meta);
// Test without title // Test without title