ENHANCEMENT FieldList->setTabPathRewrites() for better backwards compatibility (see #7261)

This commit is contained in:
Ingo Schommer 2012-05-09 17:18:16 +02:00
parent f546ab2a70
commit 8c9560d288
2 changed files with 124 additions and 0 deletions

View File

@ -25,6 +25,12 @@ class FieldList extends ArrayList {
* @todo Documentation
*/
protected $containerField;
/**
* @var array Ordered list of regular expressions,
* see {@link setTabPathRewrites()}.
*/
protected $tabPathRewrites = array();
public function __construct($items = array()) {
if (!is_array($items) || func_num_args() > 1) {
@ -255,6 +261,9 @@ class FieldList extends ArrayList {
* @return Tab The found or newly created Tab instance
*/
public function findOrMakeTab($tabName, $title = null) {
// Backwards compatibility measure: Allow rewriting of outdated tab paths
$tabName = $this->rewriteTabPath($tabName);
$parts = explode('.',$tabName);
$last_idx = count($parts) - 1;
// We could have made this recursive, but I've chosen to keep all the logic code within FieldList rather than add it to TabSet and Tab too.
@ -291,6 +300,7 @@ class FieldList extends ArrayList {
* @todo Implement similiarly to dataFieldByName() to support nested sets - or merge with dataFields()
*/
public function fieldByName($name) {
$name = $this->rewriteTabPath($name);
if(strpos($name,'.') !== false) list($name, $remainder) = explode('.',$name,2);
else $remainder = null;
@ -555,6 +565,59 @@ class FieldList extends ArrayList {
return false;
}
/**
* Ordered list of regular expressions
* matching a tab path, to their rewrite rule (through preg_replace()).
* Mainly used for backwards compatibility.
* Ensure that more specific rules are placed earlier in the list,
* and that tabs with children are accounted for in the rule sets.
*
* Example:
* $fields->setTabPathRewriting(array(
* // Rewrite specific innermost tab
* '/^Root\.Content\.Main$/' => 'Root.Content',
* // Rewrite all innermost tabs
* '/^Root\.Content\.([^.]+)$/' => 'Root.\\1',
* ));
*
* @param array $rewrites
*/
public function setTabPathRewrites($rewrites) {
$this->tabPathRewrites = $rewrites;
}
/**
* @return array
*/
public function getTabPathRewrites() {
return $this->tabPathRewrites;
}
/**
* Support function for backwards compatibility purposes.
* Caution: Volatile API, might be removed in 3.1 or later.
*
* @param String $tabname Path to a tab, e.g. "Root.Content.Main"
* @return String Rewritten path, based on {@link tabPathRewrites}
*/
protected function rewriteTabPath($name) {
$isRunningTest = (class_exists('SapphireTest', false) && SapphireTest::is_running_test());
foreach($this->getTabPathRewrites() as $regex => $replace) {
if(preg_match($regex, $name)) {
$newName = preg_replace($regex, $replace, $name);
Deprecation::notice('3.0.0', sprintf(
'Using outdated tab path "%s", please use the new location "%s" instead',
$name,
$newName
));
return $newName;
}
}
// No match found, return original path
return $name;
}
/**
* Default template rendering of a FieldList will concatenate all FieldHolder values.
*/

View File

@ -789,5 +789,66 @@ class FieldListTest extends SapphireTest {
$this->assertNotNull($visible->dataFieldByName('D2'));
}
function testRewriteTabPath() {
$fields = new FieldList(
new Tabset("Root",
$tab1Level1 = new Tab("Tab1Level1",
$tab1Level2 = new Tab("Tab1Level2"),
$tab2Level2 = new Tab("Tab2Level2")
),
$tab2Level1 = new Tab("Tab2Level1")
)
);
$fields->setTabPathRewrites(array(
'/Root\.Tab1Level1\.([^.]+)$/' => 'Root.Tab1Level1Renamed.\\1',
'/Root\.Tab1Level1$/' => 'Root.Tab1Level1Renamed',
));
$method = new ReflectionMethod($fields, 'rewriteTabPath');
$method->setAccessible(true);
$this->assertEquals(
'Root.Tab1Level1Renamed',
$method->invoke($fields, 'Root.Tab1Level1Renamed'),
"Doesn't rewrite new name"
);
$this->assertEquals(
'Root.Tab1Level1Renamed',
$method->invoke($fields, 'Root.Tab1Level1'),
'Direct aliasing on toplevel'
);
$this->assertEquals(
'Root.Tab1Level1Renamed.Tab1Level2',
$method->invoke($fields, 'Root.Tab1Level1.Tab1Level2'),
'Indirect aliasing on toplevel'
);
}
function testRewriteTabPathFindOrMakeTab() {
$fields = new FieldList(
new Tabset("Root",
$tab1Level1 = new Tab("Tab1Level1Renamed",
$tab1Level2 = new Tab("Tab1Level2"),
$tab2Level2 = new Tab("Tab2Level2")
),
$tab2Level1 = new Tab("Tab2Level1")
)
);
$fields->setTabPathRewrites(array(
'/Root\.Tab1Level1\.([^.]+)$/' => 'Root.Tab1Level1Renamed.\\1',
'/Root\.Tab1Level1$/' => 'Root.Tab1Level1Renamed',
));
$this->assertEquals($tab1Level1, $fields->findOrMakeTab('Root.Tab1Level1'),
'findOrMakeTab() with toplevel tab under old name'
);
$this->assertEquals($tab1Level1, $fields->findOrMakeTab('Root.Tab1Level1Renamed'),
'findOrMakeTab() with toplevel tab under new name'
);
$this->assertEquals($tab1Level2, $fields->findOrMakeTab('Root.Tab1Level1.Tab1Level2'),
'findOrMakeTab() with nested tab under old parent tab name'
);
$this->assertEquals($tab1Level2, $fields->findOrMakeTab('Root.Tab1Level1Renamed.Tab1Level2'),
'findOrMakeTab() with nested tab under new parent tab name'
);
}
}