1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\View\Helper;
11
12use Zend\Mvc\Controller\Plugin\FlashMessenger as PluginFlashMessenger;
13use Zend\ServiceManager\ServiceLocatorAwareInterface;
14use Zend\ServiceManager\ServiceLocatorInterface;
15use Zend\I18n\View\Helper\AbstractTranslatorHelper;
16
17/**
18 * Helper to proxy the plugin flash messenger
19 */
20class FlashMessenger extends AbstractTranslatorHelper implements ServiceLocatorAwareInterface
21{
22    /**
23     * Default attributes for the open format tag
24     *
25     * @var array
26     */
27    protected $classMessages = array(
28        PluginFlashMessenger::NAMESPACE_INFO => 'info',
29        PluginFlashMessenger::NAMESPACE_ERROR => 'error',
30        PluginFlashMessenger::NAMESPACE_SUCCESS => 'success',
31        PluginFlashMessenger::NAMESPACE_DEFAULT => 'default',
32        PluginFlashMessenger::NAMESPACE_WARNING => 'warning',
33    );
34
35    /**
36     * Templates for the open/close/separators for message tags
37     *
38     * @var string
39     */
40    protected $messageCloseString     = '</li></ul>';
41    protected $messageOpenFormat      = '<ul%s><li>';
42    protected $messageSeparatorString = '</li><li>';
43
44    /**
45     * Flag whether to escape messages
46     *
47     * @var bool
48     */
49    protected $autoEscape = true;
50
51    /**
52     * Html escape helper
53     *
54     * @var EscapeHtml
55     */
56    protected $escapeHtmlHelper;
57
58    /**
59     * Flash messenger plugin
60     *
61     * @var PluginFlashMessenger
62     */
63    protected $pluginFlashMessenger;
64
65    /**
66     * Service locator
67     *
68     * @var ServiceLocatorInterface
69     */
70    protected $serviceLocator;
71
72    /**
73     * Returns the flash messenger plugin controller
74     *
75     * @param  string|null $namespace
76     * @return FlashMessenger|PluginFlashMessenger
77     */
78    public function __invoke($namespace = null)
79    {
80        if (null === $namespace) {
81            return $this;
82        }
83        $flashMessenger = $this->getPluginFlashMessenger();
84
85        return $flashMessenger->getMessagesFromNamespace($namespace);
86    }
87
88    /**
89     * Proxy the flash messenger plugin controller
90     *
91     * @param  string $method
92     * @param  array  $argv
93     * @return mixed
94     */
95    public function __call($method, $argv)
96    {
97        $flashMessenger = $this->getPluginFlashMessenger();
98        return call_user_func_array(array($flashMessenger, $method), $argv);
99    }
100
101    /**
102     * Render Messages
103     *
104     * @param  string    $namespace
105     * @param  array     $classes
106     * @param  null|bool $autoEscape
107     * @return string
108     */
109    public function render($namespace = PluginFlashMessenger::NAMESPACE_DEFAULT, array $classes = array(), $autoEscape = null)
110    {
111        $flashMessenger = $this->getPluginFlashMessenger();
112        $messages = $flashMessenger->getMessagesFromNamespace($namespace);
113        return $this->renderMessages($namespace, $messages, $classes, $autoEscape);
114    }
115
116    /**
117     * Render Current Messages
118     *
119     * @param  string    $namespace
120     * @param  array     $classes
121     * @param  bool|null $autoEscape
122     * @return string
123     */
124    public function renderCurrent($namespace = PluginFlashMessenger::NAMESPACE_DEFAULT, array $classes = array(), $autoEscape = null)
125    {
126        $flashMessenger = $this->getPluginFlashMessenger();
127        $messages = $flashMessenger->getCurrentMessagesFromNamespace($namespace);
128        return $this->renderMessages($namespace, $messages, $classes, $autoEscape);
129    }
130
131    /**
132     * Render Messages
133     *
134     * @param string    $namespace
135     * @param array     $messages
136     * @param array     $classes
137     * @param bool|null $autoEscape
138     * @return string
139     */
140    protected function renderMessages(
141        $namespace = PluginFlashMessenger::NAMESPACE_DEFAULT,
142        array $messages = array(),
143        array $classes = array(),
144        $autoEscape = null
145    ) {
146        // Prepare classes for opening tag
147        if (empty($classes)) {
148            if (isset($this->classMessages[$namespace])) {
149                $classes = $this->classMessages[$namespace];
150            } else {
151                $classes = $this->classMessages[PluginFlashMessenger::NAMESPACE_DEFAULT];
152            }
153            $classes = array($classes);
154        }
155
156        if (null === $autoEscape) {
157            $autoEscape = $this->getAutoEscape();
158        }
159
160        // Flatten message array
161        $escapeHtml      = $this->getEscapeHtmlHelper();
162        $messagesToPrint = array();
163        $translator = $this->getTranslator();
164        $translatorTextDomain = $this->getTranslatorTextDomain();
165        array_walk_recursive(
166            $messages,
167            function ($item) use (& $messagesToPrint, $escapeHtml, $autoEscape, $translator, $translatorTextDomain) {
168                if ($translator !== null) {
169                    $item = $translator->translate(
170                        $item,
171                        $translatorTextDomain
172                    );
173                }
174
175                if ($autoEscape) {
176                    $messagesToPrint[] = $escapeHtml($item);
177                    return;
178                }
179
180                $messagesToPrint[] = $item;
181            }
182        );
183
184        if (empty($messagesToPrint)) {
185            return '';
186        }
187
188        // Generate markup
189        $markup  = sprintf($this->getMessageOpenFormat(), ' class="' . implode(' ', $classes) . '"');
190        $markup .= implode(
191            sprintf($this->getMessageSeparatorString(), ' class="' . implode(' ', $classes) . '"'),
192            $messagesToPrint
193        );
194        $markup .= $this->getMessageCloseString();
195        return $markup;
196    }
197
198    /**
199     * Set whether or not auto escaping should be used
200     *
201     * @param  bool $autoEscape
202     * @return self
203     */
204    public function setAutoEscape($autoEscape = true)
205    {
206        $this->autoEscape = (bool) $autoEscape;
207        return $this;
208    }
209
210    /**
211     * Return whether auto escaping is enabled or disabled
212     *
213     * return bool
214     */
215    public function getAutoEscape()
216    {
217        return $this->autoEscape;
218    }
219
220    /**
221     * Set the string used to close message representation
222     *
223     * @param  string $messageCloseString
224     * @return FlashMessenger
225     */
226    public function setMessageCloseString($messageCloseString)
227    {
228        $this->messageCloseString = (string) $messageCloseString;
229        return $this;
230    }
231
232    /**
233     * Get the string used to close message representation
234     *
235     * @return string
236     */
237    public function getMessageCloseString()
238    {
239        return $this->messageCloseString;
240    }
241
242    /**
243     * Set the formatted string used to open message representation
244     *
245     * @param  string $messageOpenFormat
246     * @return FlashMessenger
247     */
248    public function setMessageOpenFormat($messageOpenFormat)
249    {
250        $this->messageOpenFormat = (string) $messageOpenFormat;
251        return $this;
252    }
253
254    /**
255     * Get the formatted string used to open message representation
256     *
257     * @return string
258     */
259    public function getMessageOpenFormat()
260    {
261        return $this->messageOpenFormat;
262    }
263
264    /**
265     * Set the string used to separate messages
266     *
267     * @param  string $messageSeparatorString
268     * @return FlashMessenger
269     */
270    public function setMessageSeparatorString($messageSeparatorString)
271    {
272        $this->messageSeparatorString = (string) $messageSeparatorString;
273        return $this;
274    }
275
276    /**
277     * Get the string used to separate messages
278     *
279     * @return string
280     */
281    public function getMessageSeparatorString()
282    {
283        return $this->messageSeparatorString;
284    }
285
286    /**
287     * Set the flash messenger plugin
288     *
289     * @param  PluginFlashMessenger $pluginFlashMessenger
290     * @return FlashMessenger
291     */
292    public function setPluginFlashMessenger(PluginFlashMessenger $pluginFlashMessenger)
293    {
294        $this->pluginFlashMessenger = $pluginFlashMessenger;
295        return $this;
296    }
297
298    /**
299     * Get the flash messenger plugin
300     *
301     * @return PluginFlashMessenger
302     */
303    public function getPluginFlashMessenger()
304    {
305        if (null === $this->pluginFlashMessenger) {
306            $this->setPluginFlashMessenger(new PluginFlashMessenger());
307        }
308
309        return $this->pluginFlashMessenger;
310    }
311
312    /**
313     * Set the service locator.
314     *
315     * @param  ServiceLocatorInterface $serviceLocator
316     * @return AbstractHelper
317     */
318    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
319    {
320        $this->serviceLocator = $serviceLocator;
321        return $this;
322    }
323
324    /**
325     * Get the service locator.
326     *
327     * @return ServiceLocatorInterface
328     */
329    public function getServiceLocator()
330    {
331        return $this->serviceLocator;
332    }
333
334    /**
335     * Retrieve the escapeHtml helper
336     *
337     * @return EscapeHtml
338     */
339    protected function getEscapeHtmlHelper()
340    {
341        if ($this->escapeHtmlHelper) {
342            return $this->escapeHtmlHelper;
343        }
344
345        if (method_exists($this->getView(), 'plugin')) {
346            $this->escapeHtmlHelper = $this->view->plugin('escapehtml');
347        }
348
349        if (!$this->escapeHtmlHelper instanceof EscapeHtml) {
350            $this->escapeHtmlHelper = new EscapeHtml();
351        }
352
353        return $this->escapeHtmlHelper;
354    }
355}
356