Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit db0ac7a

Browse files
committed
Refactored provider
1 parent c605b26 commit db0ac7a

File tree

1 file changed

+87
-80
lines changed

1 file changed

+87
-80
lines changed

Provider/PhpcrMenuProvider.php

Lines changed: 87 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
use Symfony\Component\HttpFoundation\Request;
1919
use PHPCR\PathNotFoundException;
2020
use PHPCR\Util\PathHelper;
21-
use Jackalope\Session;
21+
use Jackalope\Session as JackalopeSession;
2222
use Knp\Menu\FactoryInterface;
2323
use Knp\Menu\ItemInterface;
2424
use Knp\Menu\NodeInterface;
2525
use Knp\Menu\Provider\MenuProviderInterface;
26+
use PHPCR\SessionInterface;
2627

2728
class 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

Comments
 (0)