Skip to content

Instantly share code, notes, and snippets.

@adrexia
Last active July 13, 2017 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adrexia/256a8e6a5223ad095fb8 to your computer and use it in GitHub Desktop.
Save adrexia/256a8e6a5223ad095fb8 to your computer and use it in GitHub Desktop.
Silverstripe: A list decorator that allows a list to be grouped into sub-lists by number
<?php
/**
* A list decorator that allows a list to be grouped into sub-lists by number. Based on GroupBy functionality
* @author Naomi Guyer
*/
class SplitList extends SS_ListDecorator {
/**
* @param string $num
* @return array
*/
public function splitListByNum($num) {
$result = array();
$i = 1;
foreach ($this->list as $item) {
// if $item is an Object, $index can be a method or a value,
// if $item is an array, $index is used as the index
$key = (int)ceil($i / $num);
if (array_key_exists($key, $result)) {
$result[$key]->push($item);
} else {
$result[$key] = new ArrayList(array($item));
}
$i++;
}
return $result;
}
/**
* Similar to {@link splitListByNum()}, but returns
* the data in a format which is suitable for usage in templates.
*
* @param SS_List $list reference
* @param int $num Number to split list by
* @param string $children Name of the control under which children can be iterated on
* @return ArrayList
*/
public function SplitList($list, $num = 1, $children = 'Children') {
$this->list = $list;
$grouped = $this->splitListByNum($num);
$result = new ArrayList();
$i = 1;
foreach ($grouped as $indVal => $list) {
$key = (int)ceil($i / $num);
$list = GroupedList::create($list);
$result->push(new ArrayData(array(
$key => $indVal,
$children => $list
)));
}
return $result;
}
}

Using Split List

Copy 'SplitList.php' to your project directory. To use on your SS_Lists (eg ArrayList, DataList):

Php file with SS_List:

/*
* Groups SS_List relation "MyList" for templates
* @return ArrayList
*/
public function MyListToCol($num) {
	if(!$num) {
		$num = 1; //fall back if number is not defined
	}
	$splitList = SplitList::create($this->MyList());
	return $splitList->SplitList($this->MyList(),$num);
}

Template file (.ss)

<% loop $MyList($NumToSplitBy) %>
	<div class="row">
		<% loop $Children %>
			$Title
		<% end_loop %>
	</div>
<% end_loop %>
<?php
/**
* Tests for the {@link SplitList} list decorator.
* @author Naomi Guyer
*/
class SplitListTest extends SapphireTest {
public function testSplitListByNum() {
$list = new SplitList(new ArrayList(array(
array('Name' => 'AAA'),
array('Name' => 'AAA'),
array('Name' => 'BBB'),
array('Name' => 'BBB'),
array('Name' => 'AAA'),
array('Name' => 'BBB'),
array('Name' => 'CCC'),
array('Name' => 'CCC')
)));
$split = $list->splitListByNum(4);
$this->assertEquals(2, count($split));
$this->assertEquals(4, count($split[1]));
$this->assertEquals(4, count($split[2]));
}
public function testSplitList() {
$list = SplitList::create(new ArrayList(array(
array('Name' => 'AAA'),
array('Name' => 'BBB'),
array('Name' => 'CCC'),
array('Name' => 'DDD'),
array('Name' => 'EEE'),
array('Name' => 'FFF'),
array('Name' => 'GGG')
)));
$split = $list->SplitList($list, 2);
$first = $split->first();
$last = $split->last();
$this->assertEquals(2, count($first->Children));
$this->assertEquals('AAA', $first->Name);
$this->assertEquals(1, count($last->Children));
$this->assertEquals('GGG', $last->Name);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment