1818use Symfony \Component \HttpFoundation \Request ;
1919use PHPCR \PathNotFoundException ;
2020use PHPCR \Util \PathHelper ;
21- use Jackalope \Session ;
21+ use Jackalope \Session as JackalopeSession ;
2222use Knp \Menu \FactoryInterface ;
2323use Knp \Menu \ItemInterface ;
2424use Knp \Menu \NodeInterface ;
2525use Knp \Menu \Provider \MenuProviderInterface ;
26+ use PHPCR \SessionInterface ;
2627
2728class PhpcrMenuProvider implements MenuProviderInterface
2829{
@@ -157,116 +158,81 @@ public function setRequest(Request $request = null)
157158 * menu root. You can thus pass a name or any relative path with slashes to
158159 * only load a submenu rather than a whole menu.
159160 *
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}
167162 */
168163 public function get ($ name , array $ options = array ())
169164 {
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 );
171175
172- $ menuItem = $ this ->loader ->load ($ menu );
173176 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+ ));
175181 }
176182
177183 return $ menuItem ;
178184 }
179185
180186 /**
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}
191188 */
192189 public function has ($ name , array $ options = array ())
193190 {
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 ;
195198 }
196199
197200 /**
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
199204 * @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.
203205 *
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
206207 *
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 .
209210 */
210- protected function find ($ name , array $ options, $ throw )
211+ protected function find ($ name , array $ options )
211212 {
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 ());
222216
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 );
229220 }
230221
231- return false ;
222+ $ this -> genericPrefetch ( $ session , $ path ) ;
232223 }
233224
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 );
255226
256- $ menu = $ dm ->find (null , $ path );
257227 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 ;
263229 }
264- if (!$ menu instanceof NodeInterface) {
265- if ($ throw ) {
266- throw new \InvalidArgumentException ("Menu at ' $ name' is not a valid menu node " );
267- }
268230
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+ ));
270236 }
271237
272238 return $ menu ;
@@ -281,4 +247,45 @@ protected function getObjectManager()
281247 {
282248 return $ this ->managerRegistry ->getManager ($ this ->managerName );
283249 }
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+ }
284291}
0 commit comments