setSeparator(PHP_EOL); } /** * Return headStyle object * * Returns headStyle helper object; optionally, allows specifying * * @param string $content Stylesheet contents * @param string $placement Append, prepend, or set * @param string|array $attributes Optional attributes to utilize * @return HeadStyle */ public function __invoke($content = null, $placement = 'APPEND', $attributes = []) { if ((null !== $content) && is_string($content)) { switch (strtoupper($placement)) { case 'SET': $action = 'setStyle'; break; case 'PREPEND': $action = 'prependStyle'; break; case 'APPEND': default: $action = 'appendStyle'; break; } $this->$action($content, $attributes); } return $this; } /** * Overload method calls * * @param string $method * @param array $args * @throws Exception\BadMethodCallException When no $content provided or invalid method. * @return mixed */ public function __call($method, $args) { if (preg_match('/^(?Pset|(ap|pre)pend|offsetSet)(Style)$/', $method, $matches)) { $index = null; $argc = count($args); $action = $matches['action']; if ('offsetSet' === $action) { if (0 < $argc) { $index = array_shift($args); --$argc; } } if (1 > $argc) { throw new Exception\BadMethodCallException(sprintf( 'Method "%s" requires minimally content for the stylesheet', $method )); } $content = $args[0]; $attrs = []; if (isset($args[1])) { $attrs = (array) $args[1]; } $item = $this->createData($content, $attrs); if ('offsetSet' === $action) { $this->offsetSet($index, $item); } else { $this->$action($item); } return $this; } return parent::__call($method, $args); } /** * Create string representation of placeholder * * @param string|int $indent * @return string */ public function toString($indent = null) { $indent = null !== $indent ? $this->getWhitespace($indent) : $this->getIndent(); $items = []; $this->getContainer()->ksort(); foreach ($this as $item) { if (! $this->isValid($item)) { continue; } $items[] = $this->itemToString($item, $indent); } $return = $indent . implode($this->getSeparator() . $indent, $items); $return = preg_replace("/(\r\n?|\n)/", '$1' . $indent, $return); return $return; } /** * Start capture action * * @param string $type * @param string $attrs * @throws Exception\RuntimeException * @return void */ public function captureStart($type = Placeholder\Container\AbstractContainer::APPEND, $attrs = null) { if ($this->captureLock) { throw new Exception\RuntimeException('Cannot nest headStyle captures'); } $this->captureLock = true; $this->captureAttrs = $attrs; $this->captureType = $type; ob_start(); } /** * End capture action and store * * @return void */ public function captureEnd() { $content = ob_get_clean(); $attrs = $this->captureAttrs; $this->captureAttrs = null; $this->captureLock = false; switch ($this->captureType) { case Placeholder\Container\AbstractContainer::SET: $this->setStyle($content, $attrs); break; case Placeholder\Container\AbstractContainer::PREPEND: $this->prependStyle($content, $attrs); break; case Placeholder\Container\AbstractContainer::APPEND: default: $this->appendStyle($content, $attrs); break; } } /** * Create data item for use in stack * * @param string $content * @param array $attributes * @return stdClass */ public function createData($content, array $attributes) { if (! isset($attributes['media'])) { $attributes['media'] = 'screen'; } elseif (is_array($attributes['media'])) { $attributes['media'] = implode(',', $attributes['media']); } $data = new stdClass(); $data->content = $content; $data->attributes = $attributes; return $data; } /** * Determine if a value is a valid style tag * * @param mixed $value * @return bool */ protected function isValid($value) { if (! $value instanceof stdClass || ! isset($value->content) || ! isset($value->attributes)) { return false; } return true; } /** * Convert content and attributes into valid style tag * * @param stdClass $item Item to render * @param string $indent Indentation to use * @return string */ public function itemToString(stdClass $item, $indent) { $attrString = ''; if (! empty($item->attributes)) { $enc = 'UTF-8'; if ( $this->view instanceof View\Renderer\RendererInterface && method_exists($this->view, 'getEncoding') ) { $enc = $this->view->getEncoding(); } $escaper = $this->getEscaper($enc); foreach ($item->attributes as $key => $value) { if (! in_array($key, $this->optionalAttributes)) { continue; } if ('media' === $key) { if (false === strpos($value, ',')) { if (! in_array($value, $this->mediaTypes)) { continue; } } else { $mediaTypes = explode(',', $value); $value = ''; foreach ($mediaTypes as $type) { $type = trim($type); if (! in_array($type, $this->mediaTypes)) { continue; } $value .= $type . ','; } $value = substr($value, 0, -1); } } $attrString .= sprintf(' %s="%s"', $key, $escaper->escapeHtmlAttr($value)); } } $escapeStart = $indent . '' . PHP_EOL; if ( isset($item->attributes['conditional']) && ! empty($item->attributes['conditional']) && is_string($item->attributes['conditional']) ) { $escapeStart = null; $escapeEnd = null; } $html = ''; if (null === $escapeStart && null === $escapeEnd) { // inner wrap with comment end and start if !IE if (str_replace(' ', '', $item->attributes['conditional']) === '!IE') { $html = '' . $html . ''; } return $html; } /** * Override append to enforce style creation * * @param mixed $value * @throws Exception\InvalidArgumentException * @return Placeholder\Container\AbstractContainer */ public function append($value) { if (! $this->isValid($value)) { throw new Exception\InvalidArgumentException( 'Invalid value passed to append; please use appendStyle()' ); } return $this->getContainer()->append($value); } /** * Override offsetSet to enforce style creation * * @param string|int $index * @param mixed $value * @throws Exception\InvalidArgumentException * @return void */ public function offsetSet($index, $value) { if (! $this->isValid($value)) { throw new Exception\InvalidArgumentException( 'Invalid value passed to offsetSet; please use offsetSetStyle()' ); } $this->getContainer()->offsetSet($index, $value); } /** * Override prepend to enforce style creation * * @param mixed $value * @throws Exception\InvalidArgumentException * @return Placeholder\Container\AbstractContainer */ public function prepend($value) { if (! $this->isValid($value)) { throw new Exception\InvalidArgumentException( 'Invalid value passed to prepend; please use prependStyle()' ); } return $this->getContainer()->prepend($value); } /** * Override set to enforce style creation * * @param mixed $value * @throws Exception\InvalidArgumentException * @return void */ public function set($value) { if (! $this->isValid($value)) { throw new Exception\InvalidArgumentException('Invalid value passed to set; please use setStyle()'); } $this->getContainer()->set($value); } }