18
18
use Symfony \Component \HttpFoundation \Request ;
19
19
use PHPCR \PathNotFoundException ;
20
20
use PHPCR \Util \PathHelper ;
21
- use Jackalope \Session ;
21
+ use Jackalope \Session as JackalopeSession ;
22
22
use Knp \Menu \FactoryInterface ;
23
23
use Knp \Menu \ItemInterface ;
24
24
use Knp \Menu \NodeInterface ;
25
25
use Knp \Menu \Provider \MenuProviderInterface ;
26
+ use PHPCR \SessionInterface ;
26
27
27
28
class PhpcrMenuProvider implements MenuProviderInterface
28
29
{
@@ -157,116 +158,81 @@ public function setRequest(Request $request = null)
157
158
* menu root. You can thus pass a name or any relative path with slashes to
158
159
* only load a submenu rather than a whole menu.
159
160
*
160
- * @param string $name Name of the menu to load. This can be an
161
- * absolute PHPCR path or one relative to the menu root.
162
- * @param array $options
163
- *
164
- * @return ItemInterface The menu (sub)tree starting with name.
165
- *
166
- * @throws \InvalidArgumentException if the menu can not be found.
161
+ * {@inheritDoc}
167
162
*/
168
163
public function get ($ name , array $ options = array ())
169
164
{
170
- $ menu = $ this ->find ($ name , $ options , true );
165
+ $ document = $ this ->find ($ name , $ options , true );
166
+
167
+ if (null === $ document ) {
168
+ throw new \InvalidArgumentException (sprintf (
169
+ 'Menu "%s" could not be located by the PhpcrMenuProvider ' ,
170
+ $ name
171
+ ));
172
+ }
173
+
174
+ $ menuItem = $ this ->loader ->load ($ document );
171
175
172
- $ menuItem = $ this ->loader ->load ($ menu );
173
176
if (empty ($ menuItem )) {
174
- throw new \InvalidArgumentException ("Menu at ' $ name' is misconfigured (f.e. the route might be incorrect) and could therefore not be instanciated " );
177
+ throw new \InvalidArgumentException (sprintf (
178
+ 'Menu "%s" is misconfigured (f.e. the route might be incorrect) and could therefore not be instansiated ' ,
179
+ $ name
180
+ ));
175
181
}
176
182
177
183
return $ menuItem ;
178
184
}
179
185
180
186
/**
181
- * Check if a menu node exists.
182
- *
183
- * If this method returns true, it means that you can call get() without
184
- * an exception.
185
- *
186
- * @param string $name Name of the menu to load. This can be an
187
- * absolute PHPCR path or one relative to the menu root.
188
- * @param array $options
189
- *
190
- * @return bool Whether a menu with this name can be loaded by this provider.
187
+ * {@inheritDoc}
191
188
*/
192
189
public function has ($ name , array $ options = array ())
193
190
{
194
- return $ this ->find ($ name , $ options , false ) instanceof NodeInterface;
191
+ $ document = $ this ->find ($ name , $ options );
192
+
193
+ if (null === $ document ) {
194
+ return false ;
195
+ }
196
+
197
+ return true ;
195
198
}
196
199
197
200
/**
198
- * @param string $name Name of the menu to load
201
+ * Find the named menu or `null` if the menu cannot be located.
202
+ *
203
+ * @param string $name Name of the menu to load
199
204
* @param array $options
200
- * @param bool $throw Whether to throw an exception if the menu is not
201
- * found or no valid menu. Returns false if $throw is false and there
202
- * is no menu at $name.
203
205
*
204
- * @return object|bool The menu root found with $name or false if $throw
205
- * is false and the menu was not found.
206
+ * @return ItemInterface|null
206
207
*
207
- * @throws \InvalidArgumentException Only if $throw is true throws this
208
- * exception if the name is empty or no menu found .
208
+ * @throws \RuntimeException If the found node does not implement the
209
+ * correct interface .
209
210
*/
210
- protected function find ($ name , array $ options, $ throw )
211
+ protected function find ($ name , array $ options )
211
212
{
212
- if (empty ($ name )) {
213
- if ($ throw ) {
214
- throw new \InvalidArgumentException ('The menu name may not be empty ' );
215
- }
216
-
217
- return false ;
218
- }
219
-
220
- $ dm = $ this ->getObjectManager ();
221
- $ session = $ dm ->getPhpcrSession ();
213
+ $ manager = $ this ->getObjectManager ();
214
+ $ session = $ manager ->getPhpcrSession ();
215
+ $ path = PathHelper::absolutizePath ($ name , $ this ->getMenuRoot ());
222
216
223
- try {
224
- $ path = PathHelper::absolutizePath ($ name , $ this ->getMenuRoot ());
225
- PathHelper::assertValidAbsolutePath ($ path , false , true , $ session ->getNamespacePrefixes ());
226
- } catch (RepositoryException $ e ) {
227
- if ($ throw ) {
228
- throw $ e ;
217
+ if ($ this ->getPrefetch () > 0 ) {
218
+ if ($ session instanceof JackalopeSession) {
219
+ $ this ->jackalopePrefetch ($ session , $ path );
229
220
}
230
221
231
- return false ;
222
+ $ this -> genericPrefetch ( $ session , $ path ) ;
232
223
}
233
224
234
- if ($ this ->getPrefetch () > 0 ) {
235
- try {
236
- if (
237
- $ session instanceof Session
238
- && 0 < $ session ->getSessionOption (Session::OPTION_FETCH_DEPTH )
239
- && 0 === strncmp ($ path , $ this ->getMenuRoot (), strlen ($ this ->getMenuRoot ()))
240
- ) {
241
- // we have jackalope with a fetch depth. prefetch all menu
242
- // nodes of all menues.
243
- $ session ->getNode ($ this ->getMenuRoot (), $ this ->getPrefetch () + 1 );
244
- } else {
245
- $ session ->getNode ($ path , $ this ->getPrefetch ());
246
- }
247
- } catch (PathNotFoundException $ e ) {
248
- if ($ throw ) {
249
- throw new \InvalidArgumentException (sprintf ('The menu root "%s" does not exist. ' , $ this ->getMenuRoot ()));
250
- }
251
-
252
- return false ;
253
- }
254
- }
225
+ $ menu = $ manager ->find (null , $ path );
255
226
256
- $ menu = $ dm ->find (null , $ path );
257
227
if (null === $ menu ) {
258
- if ($ throw ) {
259
- throw new \InvalidArgumentException (sprintf ('The menu "%s" is not defined. ' , $ name ));
260
- }
261
-
262
- return false ;
228
+ return null ;
263
229
}
264
- if (!$ menu instanceof NodeInterface) {
265
- if ($ throw ) {
266
- throw new \InvalidArgumentException ("Menu at ' $ name' is not a valid menu node " );
267
- }
268
230
269
- return false ;
231
+ if (!$ menu instanceof NodeInterface) {
232
+ throw new \RuntimeException (sprintf (
233
+ 'Menu document at "%s" does not implement Knp\Menu\NodeInterface ' ,
234
+ $ path
235
+ ));
270
236
}
271
237
272
238
return $ menu ;
@@ -281,4 +247,45 @@ protected function getObjectManager()
281
247
{
282
248
return $ this ->managerRegistry ->getManager ($ this ->managerName );
283
249
}
250
+
251
+ /**
252
+ * Special case for Jackalope prefetching.
253
+ */
254
+ private function jackalopePrefetch (JackalopeSession $ session , $ path )
255
+ {
256
+ $ fetchDepth = $ session ->getSessionOption (JackalopeSession::OPTION_FETCH_DEPTH );
257
+
258
+ // under what circumstance would the path not contain the menu root?
259
+ $ containsRoot = 0 === strncmp ($ path , $ this ->getMenuRoot (), strlen ($ this ->getMenuRoot ()));
260
+
261
+ if (false === $ containsRoot || 0 === $ fetchDepth ) {
262
+ return $ this ->genericPrefetch ($ session , $ path );
263
+ }
264
+
265
+ try {
266
+ // we have jackalope with a fetch depth. prefetch all menu
267
+ // nodes of all menues.
268
+ $ session ->getNode ($ this ->getMenuRoot (), $ this ->getPrefetch () + 1 );
269
+ } catch (PathNotFoundException $ e ) {
270
+ throw new \InvalidArgumentException (sprintf (
271
+ 'The menu root "%s" does not exist when prefetching for Jackalope ' ,
272
+ $ this ->getMenuRoot ()
273
+ ), null , $ e );
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Generic prefetch
279
+ */
280
+ private function genericPrefetch (SessionInterface $ session , $ path )
281
+ {
282
+ try {
283
+ $ session ->getNode ($ path , $ this ->getPrefetch ());
284
+ } catch (PathNotFoundException $ e ) {
285
+ throw new \InvalidArgumentException (sprintf (
286
+ 'The menu node "%s" does not exist. ' ,
287
+ $ path
288
+ ), null , $ e );
289
+ }
290
+ }
284
291
}
0 commit comments