/** * This query can couse some data integrity failures since it does not * execute atomicaly * * {@inheritDoc} */ public function replaceInverseRelative($object, array $config, $target, $replacement) { $dm = $this->getObjectManager(); $wrapped = AbstractWrapper::wrapp($object, $dm); $meta = $dm->getClassMetadata($config['useObjectClass']); $q = $dm->createQueryBuilder($config['useObjectClass'])->field($config['mappedBy'] . '.' . $meta->identifier)->equals($wrapped->getIdentifier())->getQuery(); $q->setHydrate(false); $result = $q->execute(); if ($result instanceof Cursor) { $result = $result->toArray(); foreach ($result as $targetObject) { $slug = preg_replace("@^{$replacement}@smi", $target, $targetObject[$config['slug']]); $dm->createQueryBuilder()->update($config['useObjectClass'])->field($config['slug'])->set($slug)->field($meta->identifier)->equals($targetObject['_id'])->getQuery()->execute(); } } }
/** * {@inheritDoc} */ public function onSlugCompletion(SluggableAdapter $ea, array &$config, $object, &$slug) { $this->om = $ea->getObjectManager(); $isInsert = $this->om->getUnitOfWork()->isScheduledForInsert($object); if (!$isInsert) { $options = $config['handlers'][get_called_class()]; $wrapped = AbstractWrapper::wrapp($object, $this->om); $oldSlug = $wrapped->getPropertyValue($config['slug']); $mappedByConfig = $this->sluggable->getConfiguration($this->om, $options['relationClass']); if ($mappedByConfig) { $meta = $this->om->getClassMetadata($options['relationClass']); if (!$meta->isSingleValuedAssociation($options['mappedBy'])) { throw new InvalidMappingException("Unable to find " . $wrapped->getMetadata()->name . " relation - [{$options['mappedBy']}] in class - {$meta->name}"); } if (!isset($mappedByConfig['slugs'][$options['inverseSlugField']])) { throw new InvalidMappingException("Unable to find slug field - [{$options['inverseSlugField']}] in class - {$meta->name}"); } $mappedByConfig['slug'] = $mappedByConfig['slugs'][$options['inverseSlugField']]['slug']; $mappedByConfig['mappedBy'] = $options['mappedBy']; $ea->replaceInverseRelative($object, $mappedByConfig, $slug, $oldSlug); $uow = $this->om->getUnitOfWork(); // update in memory objects foreach ($uow->getIdentityMap() as $className => $objects) { // for inheritance mapped classes, only root is always in the identity map if ($className !== $mappedByConfig['useObjectClass']) { continue; } foreach ($objects as $object) { if (property_exists($object, '__isInitialized__') && !$object->__isInitialized__) { continue; } $oid = spl_object_hash($object); $objectSlug = $meta->getReflectionProperty($mappedByConfig['slug'])->getValue($object); if (preg_match("@^{$oldSlug}@smi", $objectSlug)) { $objectSlug = str_replace($oldSlug, $slug, $objectSlug); $meta->getReflectionProperty($mappedByConfig['slug'])->setValue($object, $objectSlug); $ea->setOriginalObjectProperty($uow, $oid, $mappedByConfig['slug'], $objectSlug); } } } } } }
/** * Update the $node with a diferent $parent * destination * * @param EntityManager $em * @param object $node - target node * @param object $parent - destination node * @param string $position * @throws Gedmo\Exception\UnexpectedValueException * @return void */ public function updateNode(EntityManager $em, $node, $parent, $position = 'FirstChild') { $wrapped = AbstractWrapper::wrapp($node, $em); $meta = $wrapped->getMetadata(); $config = $this->listener->getConfiguration($em, $meta->name); $rootId = isset($config['root']) ? $wrapped->getPropertyValue($config['root']) : null; $identifierField = $meta->getSingleIdentifierFieldName(); $nodeId = $wrapped->getIdentifier(); $left = $wrapped->getPropertyValue($config['left']); $right = $wrapped->getPropertyValue($config['right']); $isNewNode = empty($left) && empty($right); if ($isNewNode) { $left = 1; $right = 2; } $oid = spl_object_hash($node); if (isset($this->nodePositions[$oid])) { $position = $this->nodePositions[$oid]; } $level = 0; $treeSize = $right - $left + 1; $newRootId = null; if ($parent) { $wrappedParent = AbstractWrapper::wrapp($parent, $em); $parentRootId = isset($config['root']) ? $wrappedParent->getPropertyValue($config['root']) : null; $parentLeft = $wrappedParent->getPropertyValue($config['left']); $parentRight = $wrappedParent->getPropertyValue($config['right']); if (!$isNewNode && $rootId === $parentRootId && $parentLeft >= $left && $parentRight <= $right) { throw new \Gedmo\Exception\UnexpectedValueException("Cannot set child as parent to node: {$nodeId}"); } if (isset($config['level'])) { $level = $wrappedParent->getPropertyValue($config['level']); } switch ($position) { case self::PREV_SIBLING: $newParent = $wrappedParent->getPropertyValue($config['parent']); if (!$isNewNode) { $wrapped->setPropertyValue($config['parent'], $newParent); $em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $node); } $start = $parentLeft; break; case self::NEXT_SIBLING: $newParent = $wrappedParent->getPropertyValue($config['parent']); if (!$isNewNode) { $wrapped->setPropertyValue($config['parent'], $newParent); $em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $node); } $start = $parentRight + 1; break; case self::LAST_CHILD: $start = $parentRight; $level++; break; case self::FIRST_CHILD: default: $start = $parentLeft + 1; $level++; break; } $this->shiftRL($em, $config['useObjectClass'], $start, $treeSize, $parentRootId); if (!$isNewNode && $rootId === $parentRootId && $left >= $start) { $left += $treeSize; $wrapped->setPropertyValue($config['left'], $left); } if (!$isNewNode && $rootId === $parentRootId && $right >= $start) { $right += $treeSize; $wrapped->setPropertyValue($config['right'], $right); } $newRootId = $parentRootId; } elseif (!isset($config['root'])) { $start = isset($this->treeEdges[$meta->name]) ? $this->treeEdges[$meta->name] : $this->max($em, $config['useObjectClass']); $this->treeEdges[$meta->name] = $start + 2; $start++; } else { $start = 1; $newRootId = $nodeId; } $diff = $start - $left; if (!$isNewNode) { $levelDiff = isset($config['level']) ? $level - $wrapped->getPropertyValue($config['level']) : null; $this->shiftRangeRL($em, $config['useObjectClass'], $left, $right, $diff, $rootId, $newRootId, $levelDiff); $this->shiftRL($em, $config['useObjectClass'], $left, -$treeSize, $rootId); } else { $qb = $em->createQueryBuilder(); $qb->update($config['useObjectClass'], 'node'); if (isset($config['root'])) { $qb->set('node.' . $config['root'], $newRootId); $wrapped->setPropertyValue($config['root'], $newRootId); $em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['root'], $newRootId); } if (isset($config['level'])) { $qb->set('node.' . $config['level'], $level); $wrapped->setPropertyValue($config['level'], $level); $em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['level'], $level); } if (isset($newParent)) { $wrappedNewParent = AbstractWrapper::wrapp($newParent, $em); $newParentId = $wrappedNewParent->getIdentifier(); $qb->set('node.' . $config['parent'], $newParentId); $wrapped->setPropertyValue($config['parent'], $newParent); $em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['parent'], $newParent); } $qb->set('node.' . $config['left'], $left + $diff); $qb->set('node.' . $config['right'], $right + $diff); $qb->where("node.{$identifierField} = {$nodeId}"); $qb->getQuery()->getSingleScalarResult(); $wrapped->setPropertyValue($config['left'], $left + $diff); $wrapped->setPropertyValue($config['right'], $right + $diff); $em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['left'], $left + $diff); $em->getUnitOfWork()->setOriginalEntityProperty($oid, $config['right'], $right + $diff); } }
/** * {@inheritDoc} */ public function onSlugCompletion(SluggableAdapter $ea, array &$config, $object, &$slug) { if (!$this->isInsert) { $options = $this->getOptions($object); $wrapped = AbstractWrapper::wrapp($object, $this->om); $meta = $wrapped->getMetadata(); $extConfig = $this->sluggable->getConfiguration($this->om, $meta->name); $config['useObjectClass'] = $extConfig['useObjectClass']; $target = $wrapped->getPropertyValue($config['slug']); $config['pathSeparator'] = $options['separator']; $ea->replaceRelative($object, $config, $target.$options['separator'], $slug); $uow = $this->om->getUnitOfWork(); // update in memory objects foreach ($uow->getIdentityMap() as $className => $objects) { // for inheritance mapped classes, only root is always in the identity map if ($className !== $wrapped->getRootObjectName()) { continue; } foreach ($objects as $object) { if (property_exists($object, '__isInitialized__') && !$object->__isInitialized__) { continue; } $oid = spl_object_hash($object); $objectSlug = $meta->getReflectionProperty($config['slug'])->getValue($object); if (preg_match("@^{$target}{$options['separator']}@smi", $objectSlug)) { $objectSlug = str_replace($target, $slug, $objectSlug); $meta->getReflectionProperty($config['slug'])->setValue($object, $objectSlug); $ea->setOriginalObjectProperty($uow, $oid, $config['slug'], $objectSlug); } } } } }
/** * {@inheritDoc} */ public function setTranslationValue($object, $field, $value) { $em = $this->getObjectManager(); $wrapped = AbstractWrapper::wrapp($object, $em); $meta = $wrapped->getMetadata(); $type = Type::getType($meta->getTypeOfField($field)); $value = $type->convertToPHPValue($value, $em->getConnection()->getDatabasePlatform()); $wrapped->setPropertyValue($field, $value); }
/** * Transliterates the slug and prefixes the slug * by relative one * * @param string $text * @param string $separator * @param object $object * @return string */ public function transliterate($text, $separator, $object) { $options = $this->getOptions($object); $result = call_user_func_array( $this->originalTransliterator, array($text, $separator, $object) ); $wrapped = AbstractWrapper::wrapp($object, $this->om); $relation = $wrapped->getPropertyValue($options['relationField']); if ($relation) { $wrappedRelation = AbstractWrapper::wrapp($relation, $this->om); $slug = $wrappedRelation->getPropertyValue($options['relationSlugField']); $result = $slug . $options['separator'] . $result; } $this->sluggable->setTransliterator($this->originalTransliterator); return $result; }
/** * {@inheritDoc} */ public function setTranslationValue($object, $field, $value) { $dm = $this->getObjectManager(); $wrapped = AbstractWrapper::wrapp($object, $dm); $meta = $wrapped->getMetadata(); $mapping = $meta->getFieldMapping($field); $type = Type::getType($mapping['type']); $value = $type->convertToPHPValue($value); $wrapped->setPropertyValue($field, $value); }
/** * Creates all additional translations created * through repository * * @param TranslatableAdapter $ea * @param object $object * @param boolean $inserting * @return void */ private function processAdditionalTranslations(TranslatableAdapter $ea, $object, $inserting) { $oid = spl_object_hash($object); if (isset($this->additionalTranslations[$oid])) { $om = $ea->getObjectManager(); $uow = $om->getUnitOfWork(); $wrapped = AbstractWrapper::wrapp($object, $om); $meta = $wrapped->getMetadata(); $objectId = $wrapped->getIdentifier(); $transClass = $this->getTranslationClass($ea, $meta->name); foreach ($this->additionalTranslations[$oid] as $field => $translations) { foreach ($translations as $locale => $content) { $trans = null; if (!$inserting) { $trans = $ea->findTranslation($objectId, $meta->name, $locale, $field, $transClass); } if (!$trans) { $trans = new $transClass(); $trans->setField($field); $trans->setObjectClass($meta->name); $trans->setForeignKey($objectId); $trans->setLocale($locale); } $trans->setContent($ea->getTranslationValue($object, $field, $content)); if ($inserting && !$objectId) { $this->pendingTranslationInserts[$oid][] = $trans; } elseif ($trans->getId()) { $om->persist($trans); $transMeta = $om->getClassMetadata($transClass); $uow->computeChangeSet($transMeta, $trans); } else { $ea->insertTranslationRecord($trans); } } } } }