cube = $cube; } /** * Render the given facts * * @param $facts * @return string */ abstract public function renderFacts($facts); /** * Returns the base url for the details action * * @return string */ abstract protected function getDetailsBaseUrl(); /** * Initialize all we need */ protected function initialize() { $this->started = false; $this->initializeDimensions() ->initializeFacts() ->initializeLastRow() ->initializeSummaries(); } /** * @return $this */ protected function initializeLastRow() { $object = (object) array(); foreach ($this->dimensions as $dimension) { $object->{$dimension->getName()} = null; } $this->lastRow = $object; return $this; } /** * @return $this */ protected function initializeDimensions() { $this->dimensions = $this->cube->listDimensions(); $min = 3; $cnt = count($this->dimensions); if ($cnt < $min) { $pos = 0; $diff = $min - $cnt; $this->dimensionOrder = []; foreach ($this->dimensions as $name => $_) { $this->dimensionOrder[$pos++ + $diff] = $name; } } else { $this->dimensionOrder = array_keys($this->dimensions); } $this->reversedDimensions = array_reverse($this->dimensionOrder); $this->dimensionLevels = array_flip($this->dimensionOrder); return $this; } /** * @return $this */ protected function initializeFacts() { $this->facts = $this->cube->listFacts(); return $this; } /** * @return $this */ protected function initializeSummaries() { $this->summaries = (object) array(); return $this; } /** * @param object $row * @return bool */ protected function startsDimension($row) { foreach ($this->dimensionOrder as $name) { if ($row->$name === null) { $this->summaries->$name = $this->extractFacts($row); return true; } } return false; } /** * @param $row * @return object */ protected function extractFacts($row) { $res = (object) array(); foreach ($this->facts as $fact) { $res->$fact = $row->$fact; } return $res; } public function render(View $view) { $this->view = $view; $this->initialize(); $htm = $this->beginContainer(); foreach ($this->cube->fetchAll() as $row) { $htm .= $this->renderRow($row); } return $htm . $this->closeDimensions() . $this->endContainer(); } protected function renderRow($row) { $htm = ''; if ($dimension = $this->startsDimension($row)) { return $htm; } $htm .= $this->closeDimensionsForRow($row); $htm .= $this->beginDimensionsForRow($row); $htm .= $this->renderFacts($row); $this->lastRow = $row; return $htm; } protected function beginDimensionsForRow($row) { $last = $this->lastRow; foreach ($this->dimensionOrder as $name) { if ($last->$name !== $row->$name) { return $this->beginDimensionsUpFrom($name, $row); } } return ''; } protected function beginDimensionsUpFrom($dimension, $row) { $htm = ''; $found = false; foreach ($this->dimensionOrder as $name) { if ($name === $dimension) { $found = true; } if ($found) { $htm .= $this->beginDimension($name, $row); } } return $htm; } protected function closeDimensionsForRow($row) { $last = $this->lastRow; foreach ($this->dimensionOrder as $name) { if ($last->$name !== $row->$name) { return $this->closeDimensionsDownTo($name); } } return ''; } protected function closeDimensionsDownTo($name) { $htm = ''; foreach ($this->reversedDimensions as $dimension) { $htm .= $this->closeDimension($dimension); if ($name === $dimension) { break; } } return $htm; } protected function closeDimensions() { $htm = ''; foreach ($this->reversedDimensions as $name) { $htm .= $this->closeDimension($name); } return $htm; } protected function closeDimension($name) { if (! $this->started) { return ''; } $indent = $this->getIndent($name); return $indent . ' ' . "\n" . $indent . "\n"; } protected function getIndent($name) { return str_repeat(' ', $this->getLevel($name)); } protected function beginDimension($name, $row) { $indent = $this->getIndent($name); if (! $this->started) { $this->started = true; } $view = $this->view; $dimension = $this->cube->getDimension($name); return $indent . '
' . "\n" . $indent . '
' . $this->renderDimensionLabel($name, $row) . '
' . "\n" . $indent . '
' . "\n"; } /** * Render the label for a given dimension name * * To have some context available, also * * @param $name * @param $row * @return string */ protected function renderDimensionLabel($name, $row) { $caption = $row->$name; if (empty($caption)) { $caption = '_'; } return $this->view->escape($caption); } protected function getDetailsUrl($name, $row) { $cube = $this->cube; $dimensions = array_merge(array_keys($cube->listDimensions()), $cube->listSlices()); $params = [ 'dimensions' => DimensionParams::update($dimensions)->getParams() ]; foreach ($this->cube->listDimensionsUpTo($name) as $dimensionName) { $params[$dimensionName] = $row->$dimensionName; } foreach ($this->cube->getSlices() as $key => $val) { $params[$key] = $val; } return $this->view->url( $this->getDetailsBaseUrl(), $params ); } protected function getSliceUrl($name, $row) { return $this->view->url() ->setParam($name, $row->$name); } protected function isOuterDimension($name) { return $this->reversedDimensions[0] !== $name; } protected function getDimensionClassString($name, $row) { return implode(' ', $this->getDimensionClasses($name, $row)); } protected function getDimensionClasses($name, $row) { return array('cube-dimension' . $this->getLevel($name)); } protected function getLevel($name) { return $this->dimensionLevels[$name]; } /** * @return string */ protected function beginContainer() { return '
' . "\n"; } /** * @return string */ protected function endContainer() { return '
' . "\n"; } /** * Well... just to be on the safe side */ public function __destruct() { unset($this->cube); } }