1<?php
2namespace TYPO3Fluid\Fluid\Core\ViewHelper;
3
4/*
5 * This file belongs to the package "TYPO3 Fluid".
6 * See LICENSE.txt that was shipped with this package.
7 */
8
9use TYPO3Fluid\Fluid\View\ViewInterface;
10
11/**
12 * A key/value store that can be used by ViewHelpers to communicate between each other.
13 *
14 * @api
15 */
16class ViewHelperVariableContainer
17{
18
19    /**
20     * Two-dimensional object array storing the values. The first dimension is the fully qualified ViewHelper name,
21     * and the second dimension is the identifier for the data the ViewHelper wants to store.
22     *
23     * @var array
24     */
25    protected $objects = [];
26
27    /**
28     * @var ViewInterface
29     */
30    protected $view;
31
32    /**
33     * Add a variable to the Variable Container. Make sure that $viewHelperName is ALWAYS set
34     * to your fully qualified ViewHelper Class Name
35     *
36     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
37     * @param string $key Key of the data
38     * @param mixed $value The value to store
39     * @return void
40     * @api
41     */
42    public function add($viewHelperName, $key, $value)
43    {
44        $this->addOrUpdate($viewHelperName, $key, $value);
45    }
46
47    /**
48     * Adds, or overrides recursively, all current variables defined in associative
49     * array or Traversable (with string keys!).
50     *
51     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
52     * @param array|\Traversable $variables An associative array of all variables to add
53     * @return void
54     * @api
55     */
56    public function addAll($viewHelperName, $variables)
57    {
58        if (!is_array($variables) && !$variables instanceof \Traversable) {
59            throw new \InvalidArgumentException(
60                'Invalid argument type for $variables in ViewHelperVariableContainer->addAll(). Expects array/Traversable ' .
61                'but received ' . (is_object($variables) ? get_class($variables) : gettype($variables)),
62                1501425195
63            );
64        }
65        $this->objects[$viewHelperName] = array_replace_recursive(
66            isset($this->objects[$viewHelperName]) ? $this->objects[$viewHelperName] : [],
67            $variables instanceof \Traversable ? iterator_to_array($variables) : $variables
68        );
69    }
70
71    /**
72     * Add a variable to the Variable Container. Make sure that $viewHelperName is ALWAYS set
73     * to your fully qualified ViewHelper Class Name.
74     * In case the value is already inside, it is silently overridden.
75     *
76     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
77     * @param string $key Key of the data
78     * @param mixed $value The value to store
79     * @return void
80     */
81    public function addOrUpdate($viewHelperName, $key, $value)
82    {
83        if (!isset($this->objects[$viewHelperName])) {
84            $this->objects[$viewHelperName] = [];
85        }
86        $this->objects[$viewHelperName][$key] = $value;
87    }
88
89    /**
90     * Gets a variable which is stored
91     *
92     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
93     * @param string $key Key of the data
94     * @param mixed $default Default value to use if no value is found.
95     * @return mixed The object stored
96     * @api
97     */
98    public function get($viewHelperName, $key, $default = null)
99    {
100        return $this->exists($viewHelperName, $key) ? $this->objects[$viewHelperName][$key] : $default;
101    }
102
103    /**
104     * Gets all variables stored for a particular ViewHelper
105     *
106     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
107     * @param mixed $default
108     * @return array
109     */
110    public function getAll($viewHelperName, $default = null)
111    {
112        return array_key_exists($viewHelperName, $this->objects) ? $this->objects[$viewHelperName] : $default;
113    }
114
115    /**
116     * Determine whether there is a variable stored for the given key
117     *
118     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
119     * @param string $key Key of the data
120     * @return boolean TRUE if a value for the given ViewHelperName / Key is stored, FALSE otherwise.
121     * @api
122     */
123    public function exists($viewHelperName, $key)
124    {
125        return isset($this->objects[$viewHelperName]) && array_key_exists($key, $this->objects[$viewHelperName]);
126    }
127
128    /**
129     * Remove a value from the variable container
130     *
131     * @param string $viewHelperName The ViewHelper Class name (Fully qualified, like "TYPO3Fluid\Fluid\ViewHelpers\ForViewHelper")
132     * @param string $key Key of the data to remove
133     * @return void
134     * @api
135     */
136    public function remove($viewHelperName, $key)
137    {
138        unset($this->objects[$viewHelperName][$key]);
139    }
140
141    /**
142     * Set the view to pass it to ViewHelpers.
143     *
144     * @param ViewInterface $view View to set
145     * @return void
146     */
147    public function setView(ViewInterface $view)
148    {
149        $this->view = $view;
150    }
151
152    /**
153     * Get the view.
154     *
155     * !!! This is NOT a public API and might still change!!!
156     *
157     * @return ViewInterface The View
158     */
159    public function getView()
160    {
161        return $this->view;
162    }
163
164    /**
165     * Clean up for serializing.
166     *
167     * @return array
168     */
169    public function __sleep()
170    {
171        return ['objects'];
172    }
173}
174