<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Form\View\Helper;

use 
Traversable;
use 
Zend\Form\ElementInterface;
use 
Zend\Form\Exception;

class 
FormElementErrors extends AbstractHelper
{
    
/**@+
     * @var string Templates for the open/close/separators for message tags
     */
    
protected $messageCloseString     '</li></ul>';
    protected 
$messageOpenFormat      '<ul%s><li>';
    protected 
$messageSeparatorString '</li><li>';
    
/**@-*/

    /**
     * @var array Default attributes for the open format tag
     */
    
protected $attributes = array();

    
/**
     * Set the string used to close message representation
     *
     * @param  string $messageCloseString
     * @return FormElementErrors
     */
    
public function setMessageCloseString($messageCloseString)
    {
        
$this->messageCloseString = (string) $messageCloseString;
        return 
$this;
    }

    
/**
     * Get the string used to close message representation
     *
     * @return string
     */
    
public function getMessageCloseString()
    {
        return 
$this->messageCloseString;
    }

    
/**
     * Set the formatted string used to open message representation
     *
     * @param  string $messageOpenFormat
     * @return FormElementErrors
     */
    
public function setMessageOpenFormat($messageOpenFormat)
    {
        
$this->messageOpenFormat = (string) $messageOpenFormat;
        return 
$this;
    }

    
/**
     * Get the formatted string used to open message representation
     *
     * @return string
     */
    
public function getMessageOpenFormat()
    {
        return 
$this->messageOpenFormat;
    }

    
/**
     * Set the string used to separate messages
     *
     * @param  string $messageSeparatorString
     * @return FormElementErrors
     */
    
public function setMessageSeparatorString($messageSeparatorString)
    {
        
$this->messageSeparatorString = (string) $messageSeparatorString;
        return 
$this;
    }

    
/**
     * Get the string used to separate messages
     *
     * @return string
     */
    
public function getMessageSeparatorString()
    {
        return 
$this->messageSeparatorString;
    }

    
/**
     * Set the attributes that will go on the message open format
     *
     * @param array $attributes key value pairs of attributes
     * @return FormElementErrors
     */
    
public function setAttributes(array $attributes)
    {
        
$this->attributes $attributes;
        return 
$this;
    }

    
/**
     * Get the attributes that will go on the message open format
     *
     * @return array
     */
    
public function getAttributes()
    {
        return 
$this->attributes;
    }

    
/**
     * Render validation errors for the provided $element
     *
     * @param  ElementInterface $element
     * @param  array $attributes
     * @throws Exception\DomainException
     * @return string
     */
    
public function render(ElementInterface $element, array $attributes = array())
    {
        
$messages $element->getMessages();
        if (empty(
$messages)) {
            return 
'';
        }
        if (!
is_array($messages) && !$messages instanceof Traversable) {
            throw new 
Exception\DomainException(sprintf(
                
'%s expects that $element->getMessages() will return an array or Traversable; received "%s"',
                
__METHOD__,
                (
is_object($messages) ? get_class($messages) : gettype($messages))
            ));
        }

        
// Prepare attributes for opening tag
        
$attributes array_merge($this->attributes$attributes);
        
$attributes $this->createAttributesString($attributes);
        if (!empty(
$attributes)) {
            
$attributes ' ' $attributes;
        }

        
// Flatten message array
        
$escapeHtml      $this->getEscapeHtmlHelper();
        
$messagesToPrint = array();
        
array_walk_recursive($messages, function ($item) use (&$messagesToPrint$escapeHtml) {
            
$messagesToPrint[] = $escapeHtml($item);
        });

        if (empty(
$messagesToPrint)) {
            return 
'';
        }

        
// Generate markup
        
$markup  sprintf($this->getMessageOpenFormat(), $attributes);
        
$markup .= implode($this->getMessageSeparatorString(), $messagesToPrint);
        
$markup .= $this->getMessageCloseString();

        return 
$markup;
    }

    
/**
     * Invoke helper as functor
     *
     * Proxies to {@link render()} if an element is passed.
     *
     * @param  ElementInterface $element
     * @param  array $attributes
     * @return string|FormElementErrors
     */
    
public function __invoke(ElementInterface $element null, array $attributes = array())
    {
        if (!
$element) {
            return 
$this;
        }

        return 
$this->render($element$attributes);
    }
}