/** * Move a page as sibling of $target. * * @param Page $page The page to be moved. * @param Page $target The target page. * @param boolean $asPrevious Move page as previous sibling of $target if true (default), next sibling elsewhere. * * @return Page The moved page. * * @throws InvalidArgumentException Raises if $target is a root. */ private function moveAsSiblingOf(Page $page, Page $target, $asPrevious = true) { if (null === $target->getParent()) { throw new InvalidArgumentException('Cannot move a page as sibling of a root.'); } if (!$page->hasMainSection() && $target->hasMainSection()) { $this->moveAsFirstChildOf($page, $target->getParent()); } elseif (!$page->hasMainSection() && !$target->hasMainSection()) { $this->movePageAsSiblingOf($page, $target, $asPrevious); } elseif ($page->hasMainSection() && !$target->hasMainSection()) { $this->moveAsLastChildOf($page, $target->getParent()); } else { $this->moveSectionAsSiblingOf($page, $target, $asPrevious); } return $page->setParent($target->getParent()); }
/** * Clone a page. * * @return \Symfony\Component\HttpFoundation\Response * * @Rest\RequestParam(name="title", description="Cloning page new title", requirements={ * @Assert\Length(min=3, minMessage="Title must contains atleast 3 characters"), * @Assert\NotBlank * }) * * @Rest\ParamConverter(name="source", class="BackBee\NestedNode\Page") * @Rest\ParamConverter( * name="parent", id_name="parent_uid", id_source="request", class="BackBee\NestedNode\Page", required=false * ) * @Rest\ParamConverter( * name="sibling", id_name="sibling_uid", id_source="request", class="BackBee\NestedNode\Page", required=false * ) * * @Rest\Security(expression="is_granted('CREATE', source)") */ public function cloneAction(Page $source, Page $parent = null, $sibling = null, Request $request) { // user must have view permission on chosen layout $this->granted('VIEW', $source->getLayout()); if (null !== $sibling) { $parent = $sibling->getParent(); } elseif (null === $parent) { $parent = $source->getParent(); } if (null !== $parent) { $this->granted('EDIT', $parent); } else { $this->granted('EDIT', $this->getApplication()->getSite()); } $page = $this->getPageRepository()->duplicate($source, $request->request->get('title'), $parent, true, $this->getApplication()->getBBUserToken()); $this->getApplication()->getEntityManager()->persist($page); $this->getApplication()->getEntityManager()->flush(); if (null !== $sibling) { $this->getPageRepository()->moveAsPrevSiblingOf($page, $sibling); } return $this->createJsonResponse(null, 201, ['Location' => $this->getApplication()->getRouting()->getUrlByRouteName('bb.rest.page.get', ['version' => $request->attributes->get('version'), 'uid' => $page->getUid()], '', false), 'BB-PAGE-URL' => $page->getUrl()]); }
/** * Persists the page is need and valid * * @param Page $page The page to be built. */ private function doPersistIfValid(Page $page) { if (null === $page->getParent() && !empty($this->persist)) { // If root, only persist $this->em->persist($page); return; } $method = ''; if (self::PERSIST_AS_FIRST_CHILD === $this->persist) { $method = 'insertNodeAsFirstChildOf'; } elseif (self::PERSIST_AS_LAST_CHILD === $this->persist) { $method = 'insertNodeAsLastChildOf'; } if (!empty($method)) { $this->em->getRepository('BackBee\\NestedNode\\Page')->{$method}($page, $page->getParent(), $this->isSection); $this->em->persist($page); } }
/** * Computes the URL of a page according to a scheme. * * @param array $scheme The scheme to apply * @param Page $page The page * @param AbstractClassContent $content The optionnal main content of the page * @return string The generated URL */ private function doGenerate($scheme, Page $page, AbstractClassContent $content = null) { $replacement = ['$parent' => $page->isRoot() ? '' : $page->getParent()->getUrl(false), '$title' => StringUtils::urlize($page->getTitle()), '$datetime' => $page->getCreated()->format('ymdHis'), '$date' => $page->getCreated()->format('ymd'), '$time' => $page->getCreated()->format('His')]; $matches = []; if (preg_match_all('/(\\$content->[a-z]+)/i', $scheme, $matches)) { foreach ($matches[1] as $pattern) { $property = explode('->', $pattern); $property = array_pop($property); try { $replacement[$pattern] = StringUtils::urlize($content->{$property}); } catch (\Exception $e) { $replacement[$pattern] = ''; } } } $matches = []; if (preg_match_all('/(\\$ancestor\\[([0-9]+)\\])/i', $scheme, $matches)) { foreach ($matches[2] as $level) { $ancestor = $this->application->getEntityManager()->getRepository('BackBee\\NestedNode\\Page')->getAncestor($page, $level); if (null !== $ancestor && $page->getLevel() > $level) { $replacement['$ancestor[' . $level . ']'] = $ancestor->getUrl(false); } else { $replacement['$ancestor[' . $level . ']'] = ''; } } } $url = preg_replace('/\\/+/', '/', str_replace(array_keys($replacement), array_values($replacement), $scheme)); return $this->getUniqueness($page, $url); }
/** * Is this page is an ancestor of the provided one? * * @param Page $page * @param boolean $strict Optional, if true (default) this page is excluded of ancestors list. * * @return boolean True if this page is an anscestor of provided page, false otherwise. */ public function isAncestorOf(Page $page, $strict = true) { if (!$this->hasMainSection()) { return $this === $page && false === $strict; } return $this->getSection()->isAncestorOf($page->getSection(), $strict) || $page->getParent() === $this; }
/** * @covers BackBee\NestedNode\Page::getParent() */ public function testGetParent() { $this->assertNull($this->page->getParent()); $subsection = new Section('sub-section'); $subsection->setRoot($this->page->getSection())->setParent($this->page->getSection()); $child = new Page('child', array('main_section' => $subsection)); $this->assertEquals($this->page, $child->getParent()); $subchild = new Page('child'); $subchild->setSection($child->getSection()); $this->assertEquals($child, $subchild->getParent()); }
/** * Add query part to select siblings of page. * * @param Page $page The page to look for siblings * @param boolean $strict Optional, if false (by default) $node is include to the selection * @param array|null $order Optional, ordering spec ( [$field => $sort] ) * @param integer|null $limit Optional, max number of results, if null no limit * @param integer $start Optional, first result index (0 by default) * * @return PageQueryBuilder */ public function andIsSiblingsOf(Page $page, $strict = false, array $order = null, $limit = null, $start = 0) { if (null === $page->getParent()) { $this->andParentIs(null); } else { $this->andIsDescendantOf($page->getParent(), false, $page->getLevel()); } if (true === $strict) { $suffix = $this->getSuffix(); $this->andWhere($this->getAlias() . ' != :page' . $suffix)->setParameter('page' . $suffix, $page); } if (null !== $order) { $this->addMultipleOrderBy($order); } if (null !== $limit) { $this->setMaxResults($limit)->setFirstResult($start); } return $this; }