/** * Returns the vote for class content object, recursively till AbstractClassContent. * * @param \Symfony\Component\Security\Core\Authentication\Token\TokenInterface $token * @param \BackBee\CoreDomain\ClassContent\AbstractClassContent $content * @param array $attributes * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ private function voteForClassContent(TokenInterface $token, AbstractClassContent $content, array $attributes) { if (null === $content->getProperty('category')) { return self::ACCESS_GRANTED; } if (self::ACCESS_DENIED === ($result = $this->voteForObject($token, $content, $attributes))) { if (false !== ($parent_class = get_parent_class($content))) { if ('BackBee\\CoreDomain\\ClassContent\\AbstractClassContent' !== $parent_class) { $parent_class = NAMESPACE_SEPARATOR . $parent_class; $result = $this->voteForClassContent($token, new $parent_class('*'), $attributes); } else { $objectIdentity = new ObjectIdentity('all', 'BackBee\\CoreDomain\\ClassContent\\AbstractClassContent'); $result = parent::vote($token, $objectIdentity, $attributes); } } } return $result; }
/** * Unsets a subcontent to the current collection. * * @param \BackBee\CoreDomain\ClassContent\AbstractClassContent $subContent * * @return \BackBee\CoreDomain\ClassContent\AbstractClassContent */ public function unsetSubContent(AbstractClassContent $subContent) { foreach ($this->_data as $key => $value) { if (is_array($value)) { $totalContent = count($value); foreach ($value as $cKey => $cValue) { $contentUid = $cValue; if (is_array($cValue)) { $contentUid = array_values($cValue); $contentUid = end($contentUid); } if ($subContent->getUid() == $contentUid) { if (1 === $totalContent) { $this->_data[$key] = []; $this->_subcontent->removeElement($subContent); } else { unset($value[$cKey]); $this->_data[$key] = $value; } } } } } return $this; }
/** * Runs revert post action on content and its draft. * * @param AbstractClassContent $content * @param Revision $draft * * @return ClassContentManager */ private function revertPostProcess(AbstractClassContent $content, Revision $draft) { $data = $draft->jsonSerialize(); if (0 === count($data['parameters']) && (0 === count($data['elements']) || $content instanceof ContentSet && $data['elements']['current'] === $data['elements']['draft'])) { $this->entityManager->remove($draft); if (AbstractClassContent::STATE_NEW === $content->getState()) { $classname = AbstractClassContent::getClassnameByContentType($content->getContentType()); $this->entityManager->getRepository($classname)->deleteContent($content); } } return $this; }
/** * Returns every pages that contains provided classcontent. * * @param string $contentType * @param string $contentUid * * @return \Symfony\Component\HttpFoundation\Response */ private function doGetCollectionByContent($contentType, $contentUid) { $content = null; $classname = AbstractClassContent::getClassnameByContentType($contentType); $em = $this->getDoctrine()->getManager(); try { $content = $em->find($classname, $contentUid); } catch (ClassNotFoundException $e) { throw new NotFoundHttpException("No classcontent found with provided type (:{$contentType})"); } if (null === $content) { throw new NotFoundHttpException("No `{$classname}` exists with uid `{$contentUid}`"); } $pages = $em->getRepository("BackBee\\CoreDomain\\ClassContent\\AbstractClassContent")->findPagesByContent($content); $response = $this->createResponse($this->formatCollection($pages)); if (0 < count($pages)) { $response->headers->set('Content-Range', '0-' . (count($pages) - 1) . '/' . count($pages)); } return $response; }
public function tryResolveParentObject(AbstractClassContent $parent, AbstractClassContent $element) { foreach ($parent->getData() as $key => $values) { if (!is_array($values)) { $values = array($values); } foreach ($values as $value) { if ($value instanceof AbstractClassContent) { if (!$value->isLoaded()) { // try to load subcontent if (null !== ($subcontent = $this->getApplication()->getEntityManager()->getRepository(\Symfony\Component\Security\Core\Util\ClassUtils::getRealClass($value))->load($value, $this->getRenderer()->getApplication()->getBBUserToken()))) { $value = $subcontent; } } if ($element->equals($value)) { $this->__currentelement = $key; $this->__object = $parent; $this->_parentuid = $parent->getUid(); } else { $this->tryResolveParentObject($value, $element); } } if (null !== $this->__currentelement) { break; } } if (null !== $this->__currentelement) { break; } } }
/** * Occurs on event ``bbapplication.init`` to set AbstractContent::$ignoreUnknownClassname according to bbapp parameters. * @TODO gvf this should be moved from here * * @param Event $event */ public function onApplicationInit(Event $event) { // @TODO if app is in debug mode pass the mode, this might be done outside in extension probably AbstractClassContent::throwExceptionOnUnknownClassname($this->exceptionOnUnknownClassname); }
/** * Sets the layout for the page. * Adds as much ContentSet to the page main ContentSet than defined zones in layout. * * @param Layout $layout * @param AbstractClassContent $toPushInMainZone * * @return Page */ public function setLayout(Layout $layout, AbstractClassContent $toPushInMainZone = null) { $this->_layout = $layout; $count = count($layout->getZones()); // Add as much ContentSet to the page main ContentSet than defined zones in layout for ($i = $this->getContentSet()->count(); $i < $count; $i++) { // Do this case really exists ? if (null === ($zone = $layout->getZone($i))) { $this->getContentSet()->push(new ContentSet()); continue; } // Create a new column $contentset = new ContentSet(null, $zone->options); if (null !== $toPushInMainZone && true === $zone->mainZone) { // Existing content push in the main zone $contentset->push($toPushInMainZone->setMainNode($this)); } elseif ('inherited' === $zone->defaultClassContent) { // Inherited zone => same ContentSet than parent if exist $contentset = $this->getInheritedContent($i, $contentset); } elseif ($zone->defaultClassContent) { // New default content push $contentset->push($this->createNewDefaultContent('BackBee\\CoreDomain\\ClassContent\\' . $zone->defaultClassContent, $zone->mainZone)); } $this->getContentSet()->push($contentset); } return $this; }
/** * Creates classcontent according to provided type. * * @param string $type * @param Request $request * * @return Symfony\Component\HttpFoundation\Response * * @Rest\Security("is_fully_authenticated() & has_role('ROLE_API_USER')") */ public function postAction($type, Request $request) { $classname = AbstractClassContent::getClassnameByContentType($type); $content = new $classname(); $this->granted('CREATE', $content); $this->getDoctrine()->getManager()->persist($content); $content->setDraft($this->getClassContentManager()->getDraft($content, true)); $this->getDoctrine()->getManager()->flush(); $data = $request->request->all(); if (0 < count($data)) { $data = array_merge($data, ['type' => $type, 'uid' => $content->getUid()]); $this->updateClassContent($type, $data['uid'], $data); $this->getDoctrine()->getManager()->flush(); } return $this->createJsonResponse(null, 201, ['BB-RESOURCE-UID' => $content->getUid(), 'Location' => $this->get('router')->generate('bb.rest.classcontent.get', ['version' => $request->attributes->get('version'), 'type' => $type, 'uid' => $content->getUid()])]); }
/** * Computes classcontent identifier attribute and set it to attributes property array */ private function computeIdentifierAttribute() { $data = $this->content->jsonSerialize(); $this->attributes['data-bb-identifier'] = str_replace('\\', '/', $data['type']) . '(' . $data['uid'] . ')'; }
/** * Returns true if $key is a parameter name, false otherwise. * * @param string $key The parameter to be tested * * @return boolean */ public function hasParam($key) { return $this->_content->hasParam($key); }
/** * Removes stored site-content indexes for a content in a site. * * @param Site $site * @param AbstractClassContent $content * * @return IndexationRepository */ public function removeIdxSiteContent(Site $site, AbstractClassContent $content) { $query = 'DELETE FROM idx_site_content WHERE site_uid = :site AND (content_uid IN ' . '(SELECT content_uid FROM content_has_subcontent WHERE parent_uid = :content)' . 'OR content_uid = :content)'; $params = array('site' => $site->getUid(), 'content' => $content->getUid()); return $this->_executeQuery($query, $params); }
/** * Update mainnode of the content if need during clonage. * * @param AbstractClassContent $content The cloned content. * @param array $cloningPages The cloned pages array. * @param BBUserToken|null $token Optional, the BBuser token to allow the update of revisions if set. * * @return PageRepository */ private function updateMainNodePostCloning(AbstractClassContent $content, array $cloningPages, BBUserToken $token = null) { $mainnode = $content->getMainNode(); if (null !== $mainnode && 0 < count($cloningPages) && true === in_array($mainnode->getUid(), array_keys($cloningPages))) { // Loading draft for content if (null !== $token && null !== ($draft = $this->_em->getRepository('BackBee\\CoreDomain\\ClassContent\\Revision')->getDraft($content, $token, true))) { $content->setDraft($draft); } $content->setMainNode($cloningPages[$mainnode->getUid()]); } return $this; }
/** * Deletes outdated keyword content joins. * * @param AbstractClassContent $content * @param mixed $keywords */ public function cleanKeywordLinks(AbstractClassContent $content, $keywords) { if (!is_array($keywords)) { $keywords = [$keywords]; } $keywordUids = []; foreach ($keywords as $keyword) { if ($keyword instanceof Keyword && !empty($keyword->value) && null !== ($realKeyword = $this->_em->find('BackBee\\CoreDomain\\NestedNode\\KeyWord', $keyword->value))) { $keywordUids[] = $realKeyword->getUid(); } } $query = $this->_em->getConnection()->createQueryBuilder()->select('c.keyword_uid')->from('keywords_contents', 'c'); $query->where($query->expr()->eq('c.content_uid', $query->expr()->literal($content->getUid()))); $savedKeywords = $query->execute()->fetchAll(\PDO::FETCH_COLUMN); $linksToBeRemoved = array_diff($savedKeywords, $keywordUids); if (count($linksToBeRemoved)) { $query = $this->_em->getConnection()->createQueryBuilder()->delete('keywords_contents'); array_walk($linksToBeRemoved, function (&$value, $key, $query) { $value = $query->expr()->literal($value); }, $query); $query->where($query->expr()->eq('content_uid', $query->expr()->literal($content->getUid())))->andWhere($query->expr()->in('keyword_uid', $linksToBeRemoved))->execute(); } }
/** * {@inheritdoc} */ protected function defineParam($var, $options = null) { parent::defineParam($var, $options); if ('accept' === $var) { if (null !== $options) { $this->_addAcceptedType($this->getParamValue('accept')); $this->setParam('accept', null); } } return $this; }
/** * Return the user's draft of a content, optionally checks out a new one if not exists. * * @param AbstractClassContent $content * @param BBUserToken $token * @param boolean $checkoutOnMissing If true, checks out a new revision if none was found * * @return Revision|null */ public function getDraft(AbstractClassContent $content, TokenInterface $token, $checkoutOnMissing = false) { if (null === ($revision = $content->getDraft())) { try { if (false === $this->_em->contains($content)) { $content = $this->_em->find(get_class($content), $content->getUid()); if (null === $content) { return; } } $q = $this->createQueryBuilder('r')->andWhere('r._content = :content')->andWhere('r._owner = :owner')->andWhere('r._state IN (:states)')->orderBy('r._revision', 'desc')->orderBy('r._modified', 'desc')->setParameters(['content' => $content, 'owner' => '' . UserSecurityIdentity::fromToken($token), 'states' => [Revision::STATE_ADDED, Revision::STATE_MODIFIED, Revision::STATE_CONFLICTED]])->getQuery(); $revision = $q->getSingleResult(); } catch (\Exception $e) { if ($checkoutOnMissing) { $revision = $this->checkout($content, $token); $this->_em->persist($revision); } else { $revision = null; } } } return $revision; }
/** * Returns classcontent if couple (type;uid) is valid. * * @param string $type short namespace of a classcontent * (full: BackBee\ClassContent\Block\paragraph => short: Block/paragraph) * @param string $uid * * @return AbstractClassContent */ public function findOneByTypeAndUid($type, $uid) { $content = null; $classname = AbstractClassContent::getClassnameByContentType($type); if (null === ($content = $this->findOneBy(['_uid' => $uid]))) { throw new \InvalidArgumentException(sprintf('No `%s` exists with uid `%s`.', $classname, $uid)); } return $content; }
/** * Updates states and revision number of the content. * * @param AbstractClassContent $content The content to be updated. * @param integer $revision Optional, the revision number (1 by default). * @param integer $state Optional, The state (STATE_NORMAL by default). * * @return PageBuilder The builder instance. * @codeCoverageIgnore */ private function updateContentRevision(AbstractClassContent $content, $revision = 1, $state = AbstractClassContent::STATE_NORMAL) { $content->setRevision((int) $revision); $content->setState((int) $state); return $this; }
/** * Build and/or hydrate Category object with provided classcontent. * * @param AbstractClassContent $content */ private function buildCategoryFromClassContent(AbstractClassContent $content) { foreach ((array) $content->getProperty('category') as $category) { $visible = true; if ('!' === $category[0]) { $visible = false; $category = substr($category, 1); } $id = $this->buildCategoryId($category); if (false === array_key_exists($id, $this->categories)) { $this->categories[$id] = new Category($category, $this->options); ksort($this->categories); } $this->categories[$id]->addBlock($content->getProperty('name'), $content->getProperty('description'), $content->getContentType(), $visible); } }
/** * Adds a subcontent to the colection. * * @param \BackBee\CoreDomain\ClassContent\AbstractClassContent $value * @return string the unique identifier of the add subcontent * @codeCoverageIgnore */ protected function _addSubcontent(AbstractClassContent $value) { return $value->getUid(); }