Skip to content

Commit 33a2e66

Browse files
committed
adds viewdataprovider
1 parent fca9f82 commit 33a2e66

File tree

2 files changed

+468
-0
lines changed

2 files changed

+468
-0
lines changed

src/Mvc/Views/ViewDataProvider.php

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
<?php
2+
3+
namespace Neuron\Mvc\Views;
4+
5+
use Neuron\Patterns\Registry;
6+
7+
/**
8+
* Global view data provider for the MVC framework.
9+
*
10+
* This class manages globally-shared view data that should be automatically
11+
* injected into all views. It eliminates the need for views to directly access
12+
* the Registry and provides a centralized place to configure view-level globals.
13+
*
14+
* 1. Register in an Initializer during application bootstrap
15+
* 2. Share data using share() method with static values or callables
16+
* 3. Data automatically injected into all views via Base::injectHelpers()
17+
*
18+
* @package Neuron\Mvc\Views
19+
*
20+
* @example
21+
* ```php
22+
* // In an Initializer:
23+
* $provider = ViewDataProvider::getInstance();
24+
*
25+
* // Static values
26+
* $provider->share('siteName', 'My Website');
27+
*
28+
* // Lazy evaluation (callable executed on each request)
29+
* $provider->share('currentUser', function() {
30+
* return Registry::getInstance()->get('Auth.User');
31+
* });
32+
*
33+
* // Multiple values at once
34+
* $provider->shareMultiple([
35+
* 'theme' => 'default',
36+
* 'year' => fn() => date('Y')
37+
* ]);
38+
* ```
39+
*/
40+
class ViewDataProvider
41+
{
42+
private array $_data = [];
43+
private static ?ViewDataProvider $_instance = null;
44+
45+
/**
46+
* Private constructor to enforce singleton pattern
47+
*/
48+
private function __construct()
49+
{}
50+
51+
/**
52+
* Get the singleton instance of ViewDataProvider.
53+
*
54+
* Creates and registers the instance in Registry if it doesn't exist.
55+
*
56+
* @return ViewDataProvider
57+
*/
58+
public static function getInstance(): ViewDataProvider
59+
{
60+
if( self::$_instance === null )
61+
{
62+
self::$_instance = new self();
63+
Registry::getInstance()->set( 'ViewDataProvider', self::$_instance );
64+
}
65+
66+
return self::$_instance;
67+
}
68+
69+
/**
70+
* Share a value globally with all views.
71+
*
72+
* The value can be a static value or a callable. If a callable is provided,
73+
* it will be executed each time the view data is resolved, allowing for
74+
* dynamic values that change per request.
75+
*
76+
* @param string $key The key to store the data under
77+
* @param mixed $value The value to share (can be callable for lazy evaluation)
78+
* @return ViewDataProvider Fluent interface
79+
*
80+
* @example
81+
* ```php
82+
* $provider->share('siteName', 'My Website');
83+
* $provider->share('currentUser', fn() => Auth::user());
84+
* ```
85+
*/
86+
public function share( string $key, mixed $value ): ViewDataProvider
87+
{
88+
$this->_data[ $key ] = $value;
89+
return $this;
90+
}
91+
92+
/**
93+
* Share multiple values at once.
94+
*
95+
* @param array $data Associative array of key-value pairs
96+
* @return ViewDataProvider Fluent interface
97+
*
98+
* @example
99+
* ```php
100+
* $provider->shareMultiple([
101+
* 'siteName' => 'My Website',
102+
* 'theme' => 'dark',
103+
* 'currentYear' => fn() => date('Y')
104+
* ]);
105+
* ```
106+
*/
107+
public function shareMultiple( array $data ): ViewDataProvider
108+
{
109+
foreach( $data as $key => $value )
110+
{
111+
$this->share( $key, $value );
112+
}
113+
return $this;
114+
}
115+
116+
/**
117+
* Get a shared value by key.
118+
*
119+
* If the value is a callable, it will be executed and the result returned.
120+
* If the key doesn't exist, returns the default value.
121+
*
122+
* @param string $key The key to retrieve
123+
* @param mixed $default Default value if key doesn't exist
124+
* @return mixed The resolved value
125+
*/
126+
public function get( string $key, mixed $default = null ): mixed
127+
{
128+
if( !$this->has( $key ) )
129+
{
130+
return $default;
131+
}
132+
133+
$value = $this->_data[ $key ];
134+
135+
// If value is callable, execute it and return result
136+
if( is_callable( $value ) )
137+
{
138+
return $value();
139+
}
140+
141+
return $value;
142+
}
143+
144+
/**
145+
* Check if a key exists in the shared data.
146+
*
147+
* @param string $key The key to check
148+
* @return bool True if key exists, false otherwise
149+
*/
150+
public function has( string $key ): bool
151+
{
152+
return array_key_exists( $key, $this->_data );
153+
}
154+
155+
/**
156+
* Get all shared data with callables resolved.
157+
*
158+
* This resolves all callables before returning, so the returned array
159+
* contains only static values ready for view rendering.
160+
*
161+
* @return array Associative array of all shared data with resolved values
162+
*/
163+
public function all(): array
164+
{
165+
$resolved = [];
166+
167+
foreach( $this->_data as $key => $value )
168+
{
169+
if( is_callable( $value ) )
170+
{
171+
$resolved[ $key ] = $value();
172+
}
173+
else
174+
{
175+
$resolved[ $key ] = $value;
176+
}
177+
}
178+
179+
return $resolved;
180+
}
181+
182+
/**
183+
* Remove a shared value.
184+
*
185+
* @param string $key The key to remove
186+
* @return ViewDataProvider Fluent interface
187+
*/
188+
public function remove( string $key ): ViewDataProvider
189+
{
190+
unset( $this->_data[ $key ] );
191+
return $this;
192+
}
193+
194+
/**
195+
* Clear all shared data.
196+
*
197+
* @return ViewDataProvider Fluent interface
198+
*/
199+
public function clear(): ViewDataProvider
200+
{
201+
$this->_data = [];
202+
return $this;
203+
}
204+
205+
/**
206+
* Get count of shared data items.
207+
*
208+
* @return int Number of shared items
209+
*/
210+
public function count(): int
211+
{
212+
return count( $this->_data );
213+
}
214+
}

0 commit comments

Comments
 (0)