ChartHelper

Packagecraft.app.helpers
NamespaceCraft
Inheritanceclass ChartHelper
Since2.6
Source Codecraft/app/helpers/ChartHelper.php

Class ChartHelper

Public Methods #

MethodDescriptionDefined By
getCurrencyFormat()Returns the D3 currency format based on Yii's currency formatChartHelper
getDateRanges()Returns the predefined date ranges with their label, start date and end date.ChartHelper
getDecimalFormat()Returns the D3 decimal format based on Yii's decimal formatChartHelper
getFormats()Returns the short date, decimal, percent and currency D3 formats based on Craft's locale settingsChartHelper
getPercentFormat()Returns the D3 percent format based on Yii's percent formatChartHelper
getRunChartDataFromQuery()Returns the data for a run chart, based on a given DB query, start/end dates, and the desired time interval unit.ChartHelper
getRunChartIntervalUnit()Returns the interval unit that should be used in a run chart, based on the given start and end dates.ChartHelper
getShortDateFormats()Returns the D3 short date formats based on Yii's short date formatChartHelper

Method Details #

getCurrencyFormat() #

public static function getCurrencyFormat()
{
     $format = craft()->locale->getCurrencyFormat();

     $yiiToD3Formats = array(

          '#,##0.00 ¤' => '$,.2f',
          '#,##0.00 ¤;(#,##0.00 ¤)' => '$,.2f',
          '¤#,##0.00' => '$,.2f',
          '¤#,##0.00;(¤#,##0.00)' => '$,.2f',
          '¤#,##0.00;¤-#,##0.00' => '$,.2f',
          '¤#0.00' => '$.2f',
          '¤ #,##,##0.00' => '$,.2f',
          '¤ #,##0.00' => '$,.2f',
          '¤ #,##0.00;¤-#,##0.00' => '$,.2f',
          '¤ #0.00' => '$.2f',
          '¤ #0.00;¤ #0.00-' => '$.2f',
     );

     if(isset($yiiToD3Formats[$format]))
     {
          return $yiiToD3Formats[$format];
     }
}
Returnsarray

Returns the D3 currency format based on Yii's currency format

getDateRanges() #

public static function getDateRanges()
{
     $dateRanges = array(
          'd7' => array('label' => Craft::t('Last 7 days'), 'startDate' => '-7 days', 'endDate' => null),
          'd30' => array('label' => Craft::t('Last 30 days'), 'startDate' => '-30 days', 'endDate' => null),
          'lastweek' => array('label' => Craft::t('Last Week'), 'startDate' => '-2 weeks', 'endDate' => '-1 week'),
          'lastmonth' => array('label' => Craft::t('Last Month'), 'startDate' => '-2 months', 'endDate' => '-1 month'),
     );

     return $dateRanges;
}
Returnsarray

Returns the predefined date ranges with their label, start date and end date.

getDecimalFormat() #

public static function getDecimalFormat()
{
     $format = craft()->locale->getDecimalFormat();

     $yiiToD3Formats = array(
          '#,##,##0.###' => ',.3f',
          '#,##0.###' => ',.3f',
          '#0.######' => '.6f',
          '#0.###;#0.###-' => '.3f',
          '0 mil' => ',.3f',
     );

     if(isset($yiiToD3Formats[$format]))
     {
          return $yiiToD3Formats[$format];
     }
}
Returnsarray

Returns the D3 decimal format based on Yii's decimal format

getFormats() #

public static function getFormats()
{
     return array(
          'shortDateFormats' => self::getShortDateFormats(),
          'decimalFormat' => self::getDecimalFormat(),
          'percentFormat' => self::getPercentFormat(),
          'currencyFormat' => self::getCurrencyFormat(),
     );
}
Returnsarray

Returns the short date, decimal, percent and currency D3 formats based on Craft's locale settings

getPercentFormat() #

public static function getPercentFormat()
{
     $format = craft()->locale->getPercentFormat();

     $yiiToD3Formats = array(
          '#,##,##0%' => ',.2%',
          '#,##0%' => ',.2%',
          '#,##0 %' => ',.2%',
          '#0%' => ',.0%',
          '%#,##0' => ',.2%',
     );

     if(isset($yiiToD3Formats[$format]))
     {
          return $yiiToD3Formats[$format];
     }
}
Returnsarray

Returns the D3 percent format based on Yii's percent format

getRunChartDataFromQuery() #

public static function getRunChartDataFromQuery(DbCommand $query, DateTime $startDate, DateTime $endDate, $dateColumn, $options = array())
{
     // Setup
     $options = array_merge(array(
          'intervalUnit' => null,
          'categoryLabel' => Craft::t('Date'),
          'valueLabel' => Craft::t('Value'),
          'valueType' => 'number',
     ), $options);

     if ($options['intervalUnit'] && in_array($options['intervalUnit'], array('year', 'month', 'day', 'hour')))
     {
          $intervalUnit = $options['intervalUnit'];
     }
     else
     {
          $intervalUnit = self::getRunChartIntervalUnit($startDate, $endDate);
     }


    // Convert timezone for SQL request

    $utc = new DateTime();
    $timezoneId = craft()->getTimeZone();
    $timezone = new \DateTimeZone($timezoneId);

    $offsetInSeconds = $timezone->getOffset($utc);
    $offsetInHours = round($offsetInSeconds / 60 / 60);

    $fromTz = '+00:00';
    $toTz = ($offsetInHours >= 0 ? '+' : '').$offsetInHours.':00';

    $tzDateColumn = "CONVERT_TZ({$dateColumn},'{$fromTz}','{$toTz}')";


    // Prepare the query

     switch ($intervalUnit)
     {
          case 'year':
          {
               $sqlDateFormat = '%Y-01-01';
               $phpDateFormat = 'Y-01-01';
               $sqlGroup = "YEAR({$tzDateColumn})";
               break;
          }
          case 'month':
          {
               $sqlDateFormat = '%Y-%m-01';
               $phpDateFormat = 'Y-m-01';
               $sqlGroup = "YEAR({$tzDateColumn}), MONTH({$tzDateColumn})";
               break;
          }
          case 'day':
          {
               $sqlDateFormat = '%Y-%m-%d';
               $phpDateFormat = 'Y-m-d';
               $sqlGroup = "YEAR({$tzDateColumn}), MONTH({$tzDateColumn}), DAY({$tzDateColumn})";
               break;
          }
          case 'hour':
          {
               $sqlDateFormat = '%Y-%m-%d %H:00:00';
               $phpDateFormat = 'Y-m-d H:00:00';
               $sqlGroup = "YEAR({$tzDateColumn}), MONTH({$tzDateColumn}), DAY({$tzDateColumn}), HOUR({$tzDateColumn})";
               break;
          }
     }


     // Execute the query

     $results = $query
        ->addSelect("DATE_FORMAT({$tzDateColumn}, '{$sqlDateFormat}') as date")
          ->andWhere(
               array('and', "{$tzDateColumn} >= :startDate", "{$tzDateColumn} < :endDate"),
               array(':startDate' => $startDate->format(DateTime::MYSQL_DATETIME), ':endDate' => $endDate->format(DateTime::MYSQL_DATETIME)))
          ->group($sqlGroup)
          ->order("{$tzDateColumn} asc")
          ->queryAll();


     // Assemble the data

     $rows = array();

     $cursorDate = $startDate;
     $endTimestamp = $endDate->getTimestamp();

     while ($cursorDate->getTimestamp() < $endTimestamp)
     {
          // Do we have a record for this date?
          $formattedCursorDate = $cursorDate->format($phpDateFormat);

          if (isset($results[0]) && $results[0]['date'] == $formattedCursorDate)
          {
               $value = (float) $results[0]['value'];
               array_shift($results);
          }
          else
          {
               $value = 0;
          }

          $rows[] = array($formattedCursorDate, $value);
          $cursorDate->modify('+1 '.$intervalUnit);
     }

     return array(
          'columns' => array(
               array(
                    'type' => ($intervalUnit === 'hour' ? 'datetime' : 'date'),
                    'label' => $options['categoryLabel']
               ),
               array(
                    'type' => $options['valueType'],
                    'label' => $options['valueLabel']
               )
          ),
          'rows' => $rows,
     );
}
$queryDbCommandThe DB query that should be used
$startDateDateTimeThe start of the time duration to select (inclusive)
$endDateDateTimeThe end of the time duratio to select (exclusive)
$dateColumnstringThe column that represents the date
$optionsarray / nullAny customizations that should be made over the default options
Returnsarray

Returns the data for a run chart, based on a given DB query, start/end dates, and the desired time interval unit.

The query’s SELECT clause should already be set to a column aliased as value.

The $options array can override the following defaults:

  • intervalUnit - The time interval unit to use ('hour', 'day', 'month', or 'year'). By default, a unit will be decided automatically based on the start/end date duration.
  • categoryLabel - The label to use for the chart categories (times). Defaults to "Date".
  • valueLabel - The label to use for the chart values. Defaults to "Value".
  • valueType - The type of values that are being plotted ('number', 'currency', 'percent', 'time'). Defaults to 'number'.

getRunChartIntervalUnit() #

public static function getRunChartIntervalUnit(DateTime $startDate, DateTime $endDate)
{
     // Get the total number of days between the two dates
     $days = floor(($endDate->getTimestamp() - $startDate->getTimestamp()) / 86400);

     if ($days >= 730)
     {
          return 'year';
     }

     if ($days >= 60)
     {
          return 'month';
     }

     if ($days >= 2)
     {
          return 'day';
     }

     return 'hour';
}
$startDateDateTime
$endDateDateTime
Returnsstring

The unit that the chart should use ('hour', 'day', 'month', or 'year')

Returns the interval unit that should be used in a run chart, based on the given start and end dates.

getShortDateFormats() #

public static function getShortDateFormats()
{
     $format = craft()->locale->getDateFormat('short');

     // Some of these are RTL versions
     $removals = array(
          'day' => array('y'),
          'month' => array('d', 'd‏'),
          'year' => array('d', 'd‏', 'm', 'M‏'),
     );

     $shortDateFormats = array();

     foreach($removals as $unit => $chars)
     {
          $shortDateFormats[$unit] = $format;

          foreach($chars as $char)
          {
               $shortDateFormats[$unit] = preg_replace("/(^[{$char}]+\W+|\W+[{$char}]+)/iu", '', $shortDateFormats[$unit]);
          }
     }


     // yii formats to d3 formats

     $yiiToD3Formats = array(
          'day' => array('dd' => '%-d','d' => '%-d'),
          'month' => array('MM' => '%-m','M' => '%-m'),
          'year' => array('yyyy' => '%Y','yy' => '%y','y' => '%y')
     );

     foreach($shortDateFormats as $unit => $format)
     {
          foreach($yiiToD3Formats as $_unit => $_formats)
          {
               foreach($_formats as $yiiFormat => $d3Format)
               {
                    $pattern = "/({$yiiFormat})/i";

                    preg_match($pattern, $shortDateFormats[$unit], $matches);

                    if(count($matches) > 0)
                    {
                         $shortDateFormats[$unit] = preg_replace($pattern, $d3Format, $shortDateFormats[$unit]);

                         break;
                    }

               }
          }
     }

     return $shortDateFormats;
}
Returnsarray

Returns the D3 short date formats based on Yii's short date format