src/PageTypes/DatedUpdateHolder.php
public static function ExtractMonths(
        DataList $updates,
        $link = null,
        $currentYear = null,
        $currentMonthNumber = null
    ) {
        // Set the link to current URL in the same way the HTTP::setGetVar does it.
        if (!isset($link)) {
            $link = Director::makeRelative($_SERVER['REQUEST_URI']);
        }

        $dates = $updates->dataQuery()
            ->groupby('YEAR("Date")')
            ->groupby('MONTH("Date")')
            ->query()
            ->setSelect([
                'Year' => 'YEAR("Date")',
                'Month' => 'MONTH("Date")',
            ])
            ->addWhere('"Date" IS NOT NULL')
            ->setOrderBy([
                'YEAR("Date")' => 'DESC',
                'MONTH("Date")' => 'DESC',
            ])
            ->execute();

        $years = [];
        foreach ($dates as $date) {
            $monthNumber = $date['Month'];
            $year = $date['Year'];
            $dateObj = new DateTime(implode('-', [$year, $monthNumber, 1]));
            $monthName = $dateObj->Format('M');

            // Set up the relevant year array, if not yet available.
            if (!isset($years[$year])) {
                $years[$year] = ['YearName'=>$year, 'Months' => []];
            }

            // Check if the currently processed month is the one that is selected via GET params.
            $active = false;
            if (isset($year) && isset($monthNumber)) {
                $active = (((int)$currentYear)==$year && ((int)$currentMonthNumber)==$monthNumber);
            }

            // Build the link - keep the tag and date filter, but reset the pagination.
            if ($active) {
                // Allow clicking to deselect the month.
                $link = HTTP::setGetVar('month', null, $link, '&');
                $link = HTTP::setGetVar('year', null, $link, '&');
            } else {
                $link = HTTP::setGetVar('month', $monthNumber, $link, '&');
                $link = HTTP::setGetVar('year', $year, $link, '&');
            }
            $link = HTTP::setGetVar('start', null, $link, '&');

            $years[$year]['Months'][$monthNumber] = array(
                'MonthName'=>$monthName,
                'MonthNumber'=>$monthNumber,
                'MonthLink'=>$link,
                'Active'=>$active
            );
        }

        // ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists.
        foreach ($years as &$year) {
            $year['Months'] = new ArrayList($year['Months']);
        }

        // Reverse the list so the most recent years appear first.
        return new ArrayList($years);
    }
public static function ExtractMonths(
        DataList $updates,
        $link = null,
        $currentYear = null,
        $currentMonthNumber = null
    ) {
        // Set the link to current URL in the same way the HTTP::setGetVar does it.
        if (!isset($link)) {
            $link = Director::makeRelative($_SERVER['REQUEST_URI']);
        }

        $dates = $updates->dataQuery()
            ->groupby('YEAR("Date")')
            ->groupby('MONTH("Date")')
            ->query()
            ->setSelect([
                'Year' => 'YEAR("Date")',
                'Month' => 'MONTH("Date")',
            ])
            ->addWhere('"Date" IS NOT NULL')
            ->setOrderBy([
                'YEAR("Date")' => 'DESC',
                'MONTH("Date")' => 'DESC',
            ])
            ->execute();

        $years = [];
        foreach ($dates as $date) {
            $monthNumber = $date['Month'];
            $year = $date['Year'];
            $dateObj = new DateTime(implode('-', [$year, $monthNumber, 1]));
            $monthName = $dateObj->Format('M');

            // Set up the relevant year array, if not yet available.
            if (!isset($years[$year])) {
                $years[$year] = ['YearName'=>$year, 'Months' => []];
            }

            // Check if the currently processed month is the one that is selected via GET params.
            $active = false;
            if (isset($year) && isset($monthNumber)) {
                $active = (((int)$currentYear)==$year && ((int)$currentMonthNumber)==$monthNumber);
            }

            // Build the link - keep the tag and date filter, but reset the pagination.
            if ($active) {
                // Allow clicking to deselect the month.
                $link = HTTP::setGetVar('month', null, $link, '&');
                $link = HTTP::setGetVar('year', null, $link, '&');
            } else {
                $link = HTTP::setGetVar('month', $monthNumber, $link, '&');
                $link = HTTP::setGetVar('year', $year, $link, '&');
            }
            $link = HTTP::setGetVar('start', null, $link, '&');

            $years[$year]['Months'][$monthNumber] = array(
                'MonthName'=>$monthName,
                'MonthNumber'=>$monthNumber,
                'MonthLink'=>$link,
                'Active'=>$active
            );
        }

        // ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists.
        foreach ($years as &$year) {
            $year['Months'] = new ArrayList($year['Months']);
        }

        // Reverse the list so the most recent years appear first.
        return new ArrayList($years);
    }
public static function ExtractMonths ( DataList $ updates , $ link = null , $ currentYear = null , $ currentMonthNumber = null ) { // Set the link to current URL in the same way the HTTP::setGetVar does it. if ( ! isset ( $ link ) ) { $ link = Director :: makeRelative ( $ _SERVER [ 'REQUEST_URI' ] ) ; } $ dates = $ updates -> dataQuery ( ) -> groupby ( 'YEAR("Date")' ) -> groupby ( 'MONTH("Date")' ) -> query ( ) -> setSelect ( [ 'Year' => 'YEAR("Date")' , 'Month' => 'MONTH("Date")' , ] ) -> addWhere ( '"Date" IS NOT NULL' ) -> setOrderBy ( [ 'YEAR("Date")' => 'DESC' , 'MONTH("Date")' => 'DESC' , ] ) -> execute ( ) ; $ years = [ ] ; foreach ( $ dates as $ date ) { $ monthNumber = $ date [ 'Month' ] ; $ year = $ date [ 'Year' ] ; $ dateObj = new DateTime ( implode ( '-' , [ $ year , $ monthNumber , 1 ] ) ) ; $ monthName = $ dateObj -> Format ( 'M' ) ; // Set up the relevant year array, if not yet available. if ( ! isset ( $ years [ $ year ] ) ) { $ years [ $ year ] = [ 'YearName' => $ year , 'Months' => [ ] ] ; } // Check if the currently processed month is the one that is selected via GET params. $ active = false ; if ( isset ( $ year ) && isset ( $ monthNumber ) ) { $ active = ( ( ( int ) $ currentYear ) == $ year && ( ( int ) $ currentMonthNumber ) == $ monthNumber ) ; } // Build the link - keep the tag and date filter, but reset the pagination. if ( $ active ) { // Allow clicking to deselect the month. $ link = HTTP :: setGetVar ( 'month' , null , $ link , '&' ) ; $ link = HTTP :: setGetVar ( 'year' , null , $ link , '&' ) ; } else { $ link = HTTP :: setGetVar ( 'month' , $ monthNumber , $ link , '&' ) ; $ link = HTTP :: setGetVar ( 'year' , $ year , $ link , '&' ) ; } $ link = HTTP :: setGetVar ( 'start' , null , $ link , '&' ) ; $ years [ $ year ] [ 'Months' ] [ $ monthNumber ] = array ( 'MonthName' => $ monthName , 'MonthNumber' => $ monthNumber , 'MonthLink' => $ link , 'Active' => $ active ) ; } // ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists. foreach ( $ years as & $ year ) { $ year [ 'Months' ] = new ArrayList ( $ year [ 'Months' ] ) ; } // Reverse the list so the most recent years appear first. return new ArrayList ( $ years ) ; }
Produce an ArrayList of available months out of the updates contained in the DataList.

Here is an example of the returned structure:
ArrayList:
ArrayData:
YearName => 2013
Months => ArrayList:
MonthName => Jan
MonthNumber => 1
MonthLink => (page URL)year=2012&month=1
Active => true
ArrayData:
YearName => 2012
Months => ArrayList:
...

@param DataList $updates DataList DataList to extract months from.
@param string $link Link used as abase to construct the MonthLink.
@param int $currentYear Currently selected year, for computing the link active state.
@param int $currentMonthNumber Currently selected month, for computing the link active state.

@returns ArrayList
Produce an ArrayList of available months out of the updates contained in the DataList .